Как исправить ошибки линтера

Как использовать самый популярный линтер в редакторах кода и терминале.

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

ESLint в терминале

Если у вас пока нет ESLint, его нужно установить из npm.

Давайте испытаем ESLint в действии. Попробуем написать простую функцию для вывода суммы двух чисел и с помощью ESLint проверить правильность написанного кода. Для это в терминале выполним команду

npm run lint

ESLint показывает, что нашёл 6 ошибок в файле main.js. Цифры слева говорят на какой строке, на каком символе, была найдена ошибка. Дальше в строке идёт описание ошибки. Например:

Пример описания ошибки

Текст 5 errors and 0 warnings potentially fixable with the `--fix` option после списка ошибок говорит о том, что пять из шести найденных ошибок ESLint сможет исправить автоматически.

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

Исправление ошибок

Для исправления ошибок у ESLint есть опция fix. Чтобы воспользоваться этой опцией, выполним в терминале команду

npm run lint -- --fix

Ключ --fix говорит о том, что мы хотим исправить ошибки автоматически, а два подчёркивания -- перед ключом помогают понять терминалу, что ключ относится не к команде npm run lint , а к тому, что за ней скрывается — к eslint.

ESLint исправил 5 ошибок: поправил пробелы, заменил кавычки на одинарные, удалил ненужную точку с запятой — теперь код выглядит чище. Осталось вызвать функцию, чтобы исправить последнюю ошибку. Здесь ESLint нам не поможет.

Описание ошибки

ESLint в редакторе

А что, если нам хочется сразу, в момент написания кода, знать, какие ошибки мы совершаем, и исправлять их на лету? Для этого в редактор можно установить расширение для ESLint, которое будет подсвечивать найденную ошибку прямо в файле, а при наведении подсказывать, в чём именно ошибка.

Установка расширения для ESLint в VS Code

Расширение для ESLint в VS Code может попросить подтвердить его запуск, если пакет eslint установлен локально (наш случай). Когда расширение спросит, откуда брать пакет eslint, нужно нажать «Allow», чтобы разрешить использовать eslint в текущем проекте.

Установка расширения для ESLint в VS Code

С помощью расширения для ESLint в редакторе можно автоматически исправить ошибки. Для этого нужно навести на подсвеченную ошибку, нажать кнопку Quick fix во всплывающем окошке и выбрать один из предложенных вариантов. Например, можно исправить только конкретную ошибку, а можно и все доступные разом. Если ошибка не может быть автоматически исправлена, вместо кнопки Quick fix появится текст No quick fixes available или будут предложены альтернативные варианты решения.

Установка расширения для ESLint в Atom

В Atom тоже требуется специальное расширение linter-eslint для работы ESLint. Чтобы в Atom установить расширение, нужно перейти в раздел настроек «Install Packages». Открыть его можно из окна команд (сочетание клавиш Ctrl + Shift + P на Windows и Command + Shift + P на macOS), введя в поиске «Install Packages».

Также нужный раздел настроек можно открыть через меню: Edit → Preferences → Install — на Windows, Atom → Preferences → Install — в macOS.

Установка расширения для ESLint в Atom

Далее ищем нужное расширение и устанавливаем его:

Ищем нужное расширение и устанавливаем его

После установки расширения может появиться всплывающее окно с предложением установить нужные зависимости, то есть другие расширения, с помощью которых работает linter-eslint. Для правильной работы линтера нужно установить все предложенные зависимости.

Устанавливаем все предложенные зависимости

Теперь можно приступить к исправлению ошибок, исправить большинство ошибок можно автоматически, наведя на ошибку и нажав «Fix» или снова использовать окно команд, где выполнить Linter Eslint: Fix File.

Включение поддержки ESLint в WebStorm

В WebStorm не нужно устанавливать отдельное расширение, ESLint работает в этом редакторе «из коробки», достаточно только включить поддержку ESLint. Откройте окно Preferences с настройками, перейдите на вкладку ESLint (Languages and Frameworks → JavaScript → Code Quality Tools → ESLint) и выберете автоматическую конфигурацию ESLint — Automatic ESLint configuration. При автоматической конфигурации ESLint всегда будет искать в директории проекта файл .eslintrc с правилами оформления кода и ориентироваться на него.

Исправляются ошибки так же просто, достаточно нажать правой кнопкой мыши в файле с ошибками и выбрать из списка «Fix ESLint problems».

Дополнительные материалы:

  • 34 инструмента для веб-разработчика на каждый день
  • Обзор Chrome DevTools. Решаем основные задачи разработчика
  • HTML-шаблонизаторы
  • Как проверить валидность HTML-разметки

Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

Ошибки оформления, синтаксиса и линтера

Основы Java

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

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

Если программа на Java написана синтаксически некорректно, то компилятор выводит на экран:

  • Сообщение об ошибке
  • Указание на файл
  • Строчка в файле, где по его мнению произошла ошибка

Ниже пример кода с синтаксической ошибкой:

System.out.println("alala

Если запустить код выше, то мы увидим следующее сообщение:

|  Error:
|  unclosed string literal
|  System.out.println("alala

С одной стороны, ошибки синтаксиса — самые простые, потому что они связаны исключительно с грамматическими правилами написания кода, а не с самим смыслом кода. Их легко исправить — нужно лишь найти нарушение в записи.

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

Ошибки линтера

Теперь, когда мы уже научились писать простые программы, можно немного поговорить о том, как их писать.

Код программы следует оформлять определенным образом, чтобы он был достаточно понятным и простым в поддержке.

Специальные наборы правил — стандарты — описывают различные аспекты написания кода. Конкретно в Java самым распространенным стандартом является стандарт от Sun.

В любом языке программирования существуют утилиты — так называемые линтеры. Они проверяют код на соответствие стандартам. В Java это checkstyle. Взгляните на пример:

System.out.println( "Hello, World!" ); System.out.println("I'm a developer!") ;

Линтер будет ругаться на нарушение сразу в нескольких местах:

  • ‘(‘ is followed by whitespace. [ParenPad]
  • ‘)’ is preceded with whitespace. [ParenPad]
  • ‘;’ is preceded with whitespace. [NoWhitespaceBefore]
  • Only one statement per line allowed. [OneStatementPerLine]

Проанализируем данные ошибки:

  • Правило ParenPad, указанное в квадратных скобках, требует отсутствия пробелов после открывающейся и перед закрывающейся круглыми скобками
  • Правило NoWhitespaceBefore указывает, что перед точкой с запятой не нужно устанавливать лишний пробел
  • Каждую новую инструкцию принято записывать с новой строки. На это указывает правило OneStatementPerLine

Соблюдение данных правил не влияет на результат, но помогает писать код понятнее и проще для восприятия.

Код с учетом этих правил выглядит так:

System.out.println("Hello, World!");
System.out.println("I'm a developer!");

Теперь линтер ругаться не будет. Какой мы делаем вывод? Линтер помогает писать код, который будет легче читать и анализировать.

Помните, что наличие линтера не отменяет самостоятельного анализа и упрощения чтения кода. В ваших будущих практиках на Хекслете и в реальной разработке линтер будет работать и сообщать вам о нарушениях.


Дополнительные материалы

  1. Как читать вывод тестов в Java

Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты.

Время прочтения
4 мин

Просмотры 3.2K

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

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

Даже если в проектах используется одинаковый стек технологий, каждый из них обладает своими «проектными знаниями». И в этом случае снова на помощь приходит линтер и подсказывает участнику проекта в вопросах стилизации кода, предпочтительного синтаксиса и т. д.

В данной статье мы рассмотрим настройку ESLint и Prettier для JavaScriptTypeScript и в частности для Vue.js, покажем какими правилами мы руководствуемся в проекте Shtab и почему.

Установка зависимостей

Для начала необходимо установить зависимости в окружение проекта через менеджер пакетов, мы используем yarn.

yarn add -D eslint prettier eslint-config-prettier eslint-plugin-prettier eslint-plugin-vue eslint-plugin-import @vue/eslint-config-typescript

Рассмотрим каждую зависимость:

  • eslint-config-prettier — отключает все правила, которые не нужны или могут конфликтовать с Prettier;

  • eslint-plugin-prettier — запускает Prettier как правило ESLint и сообщает о различиях как об отдельных проблемах ESLint;

  • eslint-plugin-vue — официальный плагин ESLint для Vue.js;

  • eslint-plugin-import — предназначен для поддержки анализа синтаксиса импорта/экспорта и предотвращения проблем с орфографическими ошибками в путях к файлам и именах импорта;

  • @vue/eslint-config-typescript — плагин специально разработанный для vue/cli и create-vue. Этот набор правил является базовой конфигурацией для проектов Vue-TypeScript.

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

Добавление конфигурации

Далее нужно добавить файл конфигурации .eslintrc.js (или любой другой файл формата, который поддерживает ESLint)

module.exports = {
  root: true,
  env: {
    node: true,
  },
  plugins: [@typescript - eslintt', 'import'],
  extends: [
    'eslint:recommended',
    'plugin:vue/essential',
    @vuee / typescript',
    'plugin:prettier/recommended',
  ],
}

.prettierrc.js

module.exports = {
  singleQuote: true,
  trailingComma: 'all',
  endOfLine: 'lf',
  printWidth: 100,
};

Подробно с опциями prettier можно ознакомиться в документации.

Проектные правила

Помимо основных правил vue/essential, которые предлагает eslint-plugin-vue , мы используем и другие, некоторые из которых отличаются от Style Guide, который предлагает Vue.

Снизу представлены некоторые из них:

'vue/order-in-components': [
  'error',
  {
    order: [
      'name',
      'directives',
      'components',
      'mixins',
      ['provide', 'inject'],
      'model',
      'props',
      'filters',
      'data',
      'computed',
      'watch',
      'methods',
      'LIFECYCLE_HOOKS',
      'ROUTER_GUARDS',
    ],
  },
],
'vue/v-for-delimiter-style': ['error', 'of'],
'vue/next-tick-style': ['error', 'promise'],
'vue/require-prop-types': 'error',
'vue/prop-name-casing': ['error', 'camelCase'],
'vue/component-name-in-template-casing': ['error', 'PascalCase'],
'vue/component-definition-name-casing': ['error', 'PascalCase'],
'vue/custom-event-name-casing': ['error', 'camelCase'],
'vue/no-duplicate-attr-inheritance': 'error',
'vue/this-in-template': ['error', 'never'],
'vue/v-on-style': ['error', 'shorthand'],
'vue/no-multi-spaces': 'error',
'vue/padding-line-between-blocks': 'error',
'vue/component-tags-order': [
  'error',
  {
    order: ['template', 'script', 'style'],
  },
],
'vue/v-on-event-hyphenation': ['error', 'never'],
'vue/attribute-hyphenation': ['error', 'never'],
'vue/v-bind-style': 'error',
'vue/v-slot-style': ['error', 'shorthand'],
'vue/no-unused-properties': [
  'error',
  {
    groups: ['props', 'data', 'computed', 'methods', 'setup'],
    ignorePublicMembers: true,
  },
],

С правилами eslint-plugin-vue можно ознакомиться в документации.

Интеграция с IDE

Большинство IDE имеют возможность интеграции с линтерами, в частности рассмотрим VSCode от Microsoft и WebStorm от JetBrains.

В VSCode необходимо добавить файл в корневом каталоге .vscode/settings.json и указать настройки для вашего проекта, например:

{
  "eslint.format.enable": true,
  "editor.codeActionsOnSave": {
    "source.fixAll": true
  }
}

В WebStorm необходимо перейти в соответствующий раздел настроек и, используя графический интерфейс, указать настройки: Preferences → Languages & Frameworks → JavaScript → Code Quality Tools → ESLint.

Заключение

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

Всегда рассматривайте вариант автоматизации улучшения кода, следите за обновлениями настроек и правил линтера. Если отсутствует необходимая настройка для вашего проекта, подумайте над тем, чтобы написать своё правило для линтера. Например, мы в своей команде придерживаемся отступов между опциями SFC, наше видение совпало с комьюнити и мы решили добавить данное правило в eslint-plugin-vue, если интересно узнать подробнее, можете обратиться к следующему Pull Request.

И наконец, если у вас есть предложения, вопросы, мы с радостью ответим, это должно помочь нам делать проекты лучше.

Материал подготовили:

Максим Стихарев – технический директор Shtab

Магомед Чемурзиев – frontend-разработчик Shtab

4 марта, 2021 1:31 пп
20 855 views
| Комментариев нет

Development, Java

Если вы пишете JavaScript в редакторе, например в Visual Studio Code, у вас есть несколько способов убедиться, что ваш код имеет правильный синтаксис и соответствует передовым практикам. Для этого можно использовать линтер. Линтеры – это программы, которые проверяют ваш код на наличие синтаксических ошибок и выделяют их, чтобы вы могли быстро их найти и исправить. ESLint – это линтер, который вы можете интегрировать в Visual Studio Code, чтобы обеспечить целостность вашего кода.

ESLint может форматировать код и анализировать его, а также вносить предложения по улучшению. Кроме того, вы можете настроить способ оценки вашего кода.

В этом руководстве вы узнаете, как установить ESLint на Visual Studio Code и реализовать пользовательскую конфигурацию для работы с операторами логов при отладке. Также мы покажем, как настроить автоматическое исправление синтаксических ошибок в ESLint при сохранении файлов.

Требования

  • П​оследняя версия Visual Studio Code на вашем компьютере. В этом руководстве используется Visual Studio Code 1.43.0.
  • Последняя версия Node на вашем компьютере. Вы можете следовать инструкциям по установке Node.js в macOS, Debian 10, CentOS 8, Ubuntu 20.04.

1: Создание простого кода JavaScript

Мы начнем с подготовки тестового проекта, на примере которого рассмотрим функции линтера. Создайте для своего проекта каталог с помощью следующей команды:

mkdir linting

Теперь, когда папка для проекта готова, перейдите в нее:

cd linting

Находясь внутри каталога linting, создайте файл JavaScript по имени app.js:

touch app.js

Откройте app.js в Visual Studio Code. Поместите следующий код JavaScript в файл app.js:

const name = 'James'

const person = {first: name}

console.log(person)

const sayHelloLinting = (fName) => {

console.log(`Hello linting, ${fName}`);

};

С точки зрения форматирования вы можете сразу заметить несколько вещей, которые можно улучшить:

  • Кавычки использованы непоследовательно.
  • Точка с запятой – тоже.
  • Интервалы установлены неправильно.

Подготовив этот файл JavaScript, вы можете инициализировать этот проект. Для этого вернитесь в командную строку и в каталоге linting выполните следующую команду:

npm init

Команда npm init при инициализации вашего проекта создаст в каталоге linting файл package.json. В package.json будут храниться зависимости и другие важные параметры конфигурации вашего проекта.

Теперь, когда тестовый проект JavaScript готов, мы можем установить ESLint.

2: Установка и настройка ESLint

Чтобы установить ESLint, введите:

npm install eslint --save-dev

В эту команду важно включить флаг –save-dev, поскольку он сохраняет пакет как зависимость разработки – и тогда он будет использован только в разработке, но не в производстве. Пакет eslint нужен только тогда, когда вы активно работаете над кодом и вносите изменения в свой проект. Как только ваш проект будет на стадии производства, eslint больше не понадобится. И флаг –save-dev гарантирует, что eslint будет указан в вашем файле package.json только как зависимость разработки.

Теперь, когда ESLint установлен, вы можете инициализировать конфигурацию ESLint для своего проекта, используя для этого следующую команду:

./node_modules/.bin/eslint --init

Важным элементом этой команды является флаг –init. Раздел ./node_modules/.bin/eslint этой команды – это путь к ESLint в вашем проекте. Флаг –init активирует ESLint для вашего проекта. Процедура активации или инициализации ESLint создаст конфигурационный файл, который позволит вам настроить ESLint для вашего проекта.

Прежде чем вы сможете получить доступ к своему конфигурационному файлу ESLint, программа задаст вам несколько вопросов о проекте. Эти вопросы помогут программе убедиться, что конфигурация, инициализированная для вашего проекта, наилучшим образом соответствует требованиям.

Первый вопрос будет выглядеть так:

? How would you like to use ESLint? …

  To check syntax only

  To check syntax and find problems

❯ To check syntax, find problems, and enforce code style

Здесь мы выберем To check syntax, find problems, and enforce code style – чтобы программа проверяла синтаксис, сообщала о проблемах и поддерживала единый стиль кода.

Следующий вопрос выглядит так:

What type of modules does your project use? …

  JavaScript modules (import/export)

❯ CommonJS (require/exports)

  None of these

Выберите опцию CommonJS, чтобы использовать глобальные переменные CommonJS.

В следующем вопросе будет сказано:

? Which framework does your project use? …

  React

  Vue.js

❯ None of these

Выберите вариант None of these.

Затем программа спросит:

? Does your project use TypeScript? › No / Yes

Выберите вариант No.

Затем появится такой вопрос:

? Where does your code run? …  (Press <space> to select, <a> to toggle all, <i> to invert selection)

✔ Browser

✔ Node

Выберите Browser.

Затем вы увидите такой вопрос:

✔ How would you like to define a style for your project? …

❯ Use a popular style guide

  Answer questions about your style

  Inspect your JavaScript file(s)

Выберите ответ Use a popular style guide.

На вопрос:

Which style guide do you want to follow? 

Ответьте Airbnb: https://github.com/airbnb/javascript.

Затем будет такой вопрос:

? What format do you want your config file to be in? …

  JavaScript

  YAML

❯ JSON

Нужно выбрать JSON.

Вы получите такое сообщение:

Checking peerDependencies of eslint-config-airbnb-base@latest

The config that you've selected requires the following dependencies:

eslint-config-airbnb-base@latest eslint@^5.16.0 || ^6.8.0 || ^7.2.0 eslint-plugin-import@^2.21.2

Последний вопрос программы выглядит так:

? Would you like to install them now with npm? › No / Yes

Выберите вариант Yes, чтобы установить зависимости с помощью npm.

Вам также будет предложено установить дополнительные пакеты. Выберите yes.

После всех вопросов вы заметите, что в ваш каталог linting был добавлен файл .eslintrc.json. Теперь инструмент ESLint установлен. Код в app.js пока не изменился – и это связано с тем, что ESLint необходимо интегрировать с Visual Studio Code.

3: Настройка ESLint

Чтобы интегрировать ESLint в Visual Studio Code, вам необходимо установить расширение ESLint для VS Code. Вернитесь в Visual Studio Code и найдите ESLint во вкладке Extensions. После того, как вы найдете это расширение, нажмите Install.

После установки расширения ESLint вы заметите красочное подчеркивание в файле app.js – это линтер выделил ошибки в файле. Отметки в ESLint имеют разные цвета в зависимости от степени серьезности. Если вы наведете курсор на подчеркнутый код, вы увидите сообщение, объясняющее вам ошибку. Таким образом, ESLint помогает находить ошибки в коде и устранять их.

ESLint может сделать для вас даже больше: к примеру, он может автоматически исправлять ошибки при каждом сохранении файла (для этого требуется отдельная настройка).

4: Форматирование при сохранении

Чтобы ESLint мог автоматически исправлять синтаксис и устранять ошибки форматирования при каждом сохранении, вам нужно открыть меню настроек. Меню в Visual Studio Code – это значок шестеренки в левом нижнем углу. Нажмите его и выберите Settings.

В меню настроек найдите Code Actions on Save. Первой идет опция Editor: Code Actions on Save, а ниже – Edit in settings.json, и как раз она нам нужна.

Файл settings.json откроется в редакторе кода. Чтобы ESLint исправлял ошибки при сохранении файла, вам нужно добавить следующий код в settings.json:

"editor.codeActionsOnSave": {

  "source.fixAll.eslint": true

},

"eslint.validate": ["javascript"]

С помощью этого кода ESLint сможет автоматически исправляет ошибки и проверяет JavaScript при сохранении.

Вернитесь к файлу app.js и сохраните его. Вы увидите, что линтер внес некоторые изменения, и цвет подчеркивания тоже изменился. Вот некоторые из ошибок форматирования, которые исправил ESLint:

  • Теперь одинарные кавычки использованы последовательно.
  • Точки с запятой – тоже.
  • Отступ внутри функции расставлены правильно.

ESLint автоматически будет устранять синтаксические ошибки при сохранении файла app.js. Но пока у нас еще остались сообщения об ошибках. Их можно исправить, настроив ESLint для обнаружения или игнорирования определенных ошибок и проблем с форматированием.

5: Пользовательская настройка ESLint

«Из коробки» ESLint подчеркивает все операторы console.log() в app.js. В некоторых случаях распознавание операторов console.log в качестве ошибки может быть не в приоритете. Вы можете игнорировать операторы console.log.

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

Откройте файл .eslintrc.json. В этом файле вы увидите такой код:

{

    "env": {

        "browser": true,

        "commonjs": true,

        "es2021": true

    },

    "extends": [

        "airbnb-base"

    ],

    "parserOptions": {

        "ecmaVersion": 12

    },

    "rules": {

    }

}

В конце файла .eslintrc.json вы увидите объект «rules». Чтобы настроить триггеры ESLint (или отключить реакцию ESLint на определенные фрагменты кода), нужно добавить пары «ключ-значение» к объекту «rules». Ключ – это название правила, которое нужно добавить или изменить. Значение задает уровень серьезности проблемы. ESLint поддерживает три уровня серьезности:

  • error – подчеркивается красным
  • warn – подчеркивается желтое
  • off – ничего неподчеркивается.

Если вы не хотите подчеркивать операторы console.log как ошибки, вы можете назвать правило no-console и указать это имя в качестве ключа. Используйте off как значение:

"rules" : {

  "no-console": "off"

}

Это правило удаляет подчеркивание операторов console.log в app.js.

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

"rules" : {

  "no-console": "off",

   "quotes": [

      "error",

      "double"

    ]

}

Если теперь вы включите в код одинарные кавычки, ESLint выдаст ошибку.

Заключение

Это руководство вкратце знакомит с некоторыми функциями интеграции ESLint в Visual Studio Code. Инструменты линтинга, такие как ESLint, помогут вам сэкономить время для более сложных задач за счет автоматизации и упрощения проверки синтаксиса и остальных требований к коду.

Если вам нужна дополнительная информация о правилах и о том, какие пары «ключ-значение» вы можете использовать для настройки ESLint, вы можете ознакомиться с документацией.

Tags: ESLint, Javascript, Node.js, Visual Studio Code

In my Chai tests I often find myself wanting to use their assertions that are something like .to.be.empty, .to.be.true e.t.c., because I find them to be cleaner to read than .to.be.length(1) or .to.be.equal(true). However, this breaks my linter (I’m using default Airbnb linting).

I could use the // disable-eslint-line syntax, but then I’d have to add it to every single line that reads like that and that seems tedious.

I’ve also read about the DirtyChai library, but that would require me to go back through my entire testing library adding brackets to them all which seems like something I shouldn’t have to do simply to get my linter to pass something it should probably be OK with in the first place.

Does anyone know a nicer way to handle this than the ways I’ve outlined above?

d4nyll's user avatar

d4nyll

11.5k6 gold badges53 silver badges66 bronze badges

asked Jun 1, 2016 at 3:13

Ben Hare's user avatar

1

You can disable the rule for the entire file using eslint-disable at the top of the file in question:

/* eslint-disable no-unused-expressions */
expect(someTrueValue).to.be.true; 

However, adding this at the top of every test file can be tedious. To disable this rule for all relevant files, you can:

  1. Put a new .eslintc configuration file in the same directory as your test files, configured to disable that rule. This allows you to use the default configuration for all other rules while ignoring that rule specifically only on files in that folder. ESLint calls this Configuration Cascading.

    {
        "rules": {
            "no-unused-expressions": "off"
        }
    }
    
  2. Use the overrides key in your main .eslintrc file to disable rules for groups of files with glob pattern matching:

    {
        "overrides": [
            {
                "files": ["*.test.js", "*.spec.js"],
                "rules": {
                    "no-unused-expressions": "off"
                }
            }
        ]
    }
    

This also allows you to disable other rules which become troublesome in testing, such as no-underscore-dangle when using rewire.

answered Jun 12, 2016 at 17:51

Nick Bartlett's user avatar

Nick BartlettNick Bartlett

4,7552 gold badges23 silver badges37 bronze badges

2

I’ve made a small plugin called eslint-plugin-chai-friendly that overrides the default no-unused-expressions rule and makes it friendly towards chai. The modified rule ignores the expect and should statements while keeping default behavior for everything else.

Fabio says Reinstate Monica's user avatar

answered Apr 20, 2017 at 16:48

Ihor Diachenko's user avatar

2

Just found another option using Relative Glob Patterns:

In your .eslintrc file:

"overrides": [
    {
        "files": "*.test.js",
        "rules": {
          "no-unused-expressions": "off"
        }
    }
]

Walter Tross's user avatar

Walter Tross

12.1k2 gold badges40 silver badges63 bronze badges

answered Sep 25, 2017 at 19:08

jonalvarezz's user avatar

jonalvarezzjonalvarezz

7096 silver badges4 bronze badges

Combining jonalvarezz’s answer with Ihor Diachenko’s answer gave me exactly what I wanted:

npm install --save-dev eslint-plugin-chai-friendly

// .eslintrc.js
module.exports = {
  // ...
  plugins: ['chai-friendly'],
  overrides: [{
    files: '*.test.js',
    rules: {
      'no-unused-expressions': 'off',
      'chai-friendly/no-unused-expressions': 'error',
    },
  }],
  // ...
}

This way, the no-unused-expression rule will only be overridden in *.test.js files
AND
a no-unused-expression rule will still be in place to catch any unused expressions in the test files that are unrelated to chai.

Iman Mahmoudinasab's user avatar

answered Sep 13, 2018 at 16:11

Scott Rudiger's user avatar

2

In case anyone is stumbling upon this today, I had the same issue and found this solution on eslint documentation. In your eslint configuration file, you can specify one or several environments, which will predefine global variables for this environment. For us, it’d be mocha, and you’d configure like this in your .eslintrc.json:

{
    "env": {
        "mocha": true
    },
    ...
    ...
    ...
}

As a result, it will remove all false positive about mocha describe, it, beforeEach, etc. without needing to completely disable eslint or completely disable any specific rule.

Tested with ESLint v.4.11 and mocha 5.0

answered Feb 14, 2018 at 20:51

Pierre-Adrien's user avatar

2

I had this issue with tslint and solved it by simply moving the rule for unused expressions down one level. My ./tslint.json has all the other rules I care about, then I made ./src/tslint.json that just looks like

{
    "rules": {
        "no-unused-expression": true
    },
    "extends": "../tslint.json"
}

tslint automatically checks for a config file in every level as it descends the tree (with --project or using the VSCode extension) so this means that my tests (under ./test/) have all the other rules applied, but no-unused-expression only applies to files under ./src/.

answered Aug 1, 2019 at 10:45

Coderer's user avatar

CodererCoderer

24.9k27 gold badges93 silver badges142 bronze badges

In my Chai tests I often find myself wanting to use their assertions that are something like .to.be.empty, .to.be.true e.t.c., because I find them to be cleaner to read than .to.be.length(1) or .to.be.equal(true). However, this breaks my linter (I’m using default Airbnb linting).

I could use the // disable-eslint-line syntax, but then I’d have to add it to every single line that reads like that and that seems tedious.

I’ve also read about the DirtyChai library, but that would require me to go back through my entire testing library adding brackets to them all which seems like something I shouldn’t have to do simply to get my linter to pass something it should probably be OK with in the first place.

Does anyone know a nicer way to handle this than the ways I’ve outlined above?

d4nyll's user avatar

d4nyll

11.5k6 gold badges53 silver badges66 bronze badges

asked Jun 1, 2016 at 3:13

Ben Hare's user avatar

1

You can disable the rule for the entire file using eslint-disable at the top of the file in question:

/* eslint-disable no-unused-expressions */
expect(someTrueValue).to.be.true; 

However, adding this at the top of every test file can be tedious. To disable this rule for all relevant files, you can:

  1. Put a new .eslintc configuration file in the same directory as your test files, configured to disable that rule. This allows you to use the default configuration for all other rules while ignoring that rule specifically only on files in that folder. ESLint calls this Configuration Cascading.

    {
        "rules": {
            "no-unused-expressions": "off"
        }
    }
    
  2. Use the overrides key in your main .eslintrc file to disable rules for groups of files with glob pattern matching:

    {
        "overrides": [
            {
                "files": ["*.test.js", "*.spec.js"],
                "rules": {
                    "no-unused-expressions": "off"
                }
            }
        ]
    }
    

This also allows you to disable other rules which become troublesome in testing, such as no-underscore-dangle when using rewire.

answered Jun 12, 2016 at 17:51

Nick Bartlett's user avatar

Nick BartlettNick Bartlett

4,7552 gold badges23 silver badges37 bronze badges

2

I’ve made a small plugin called eslint-plugin-chai-friendly that overrides the default no-unused-expressions rule and makes it friendly towards chai. The modified rule ignores the expect and should statements while keeping default behavior for everything else.

Fabio says Reinstate Monica's user avatar

answered Apr 20, 2017 at 16:48

Ihor Diachenko's user avatar

2

Just found another option using Relative Glob Patterns:

In your .eslintrc file:

"overrides": [
    {
        "files": "*.test.js",
        "rules": {
          "no-unused-expressions": "off"
        }
    }
]

Walter Tross's user avatar

Walter Tross

12.1k2 gold badges40 silver badges63 bronze badges

answered Sep 25, 2017 at 19:08

jonalvarezz's user avatar

jonalvarezzjonalvarezz

7096 silver badges4 bronze badges

Combining jonalvarezz’s answer with Ihor Diachenko’s answer gave me exactly what I wanted:

npm install --save-dev eslint-plugin-chai-friendly

// .eslintrc.js
module.exports = {
  // ...
  plugins: ['chai-friendly'],
  overrides: [{
    files: '*.test.js',
    rules: {
      'no-unused-expressions': 'off',
      'chai-friendly/no-unused-expressions': 'error',
    },
  }],
  // ...
}

This way, the no-unused-expression rule will only be overridden in *.test.js files
AND
a no-unused-expression rule will still be in place to catch any unused expressions in the test files that are unrelated to chai.

Iman Mahmoudinasab's user avatar

answered Sep 13, 2018 at 16:11

Scott Rudiger's user avatar

2

In case anyone is stumbling upon this today, I had the same issue and found this solution on eslint documentation. In your eslint configuration file, you can specify one or several environments, which will predefine global variables for this environment. For us, it’d be mocha, and you’d configure like this in your .eslintrc.json:

{
    "env": {
        "mocha": true
    },
    ...
    ...
    ...
}

As a result, it will remove all false positive about mocha describe, it, beforeEach, etc. without needing to completely disable eslint or completely disable any specific rule.

Tested with ESLint v.4.11 and mocha 5.0

answered Feb 14, 2018 at 20:51

Pierre-Adrien's user avatar

2

I had this issue with tslint and solved it by simply moving the rule for unused expressions down one level. My ./tslint.json has all the other rules I care about, then I made ./src/tslint.json that just looks like

{
    "rules": {
        "no-unused-expression": true
    },
    "extends": "../tslint.json"
}

tslint automatically checks for a config file in every level as it descends the tree (with --project or using the VSCode extension) so this means that my tests (under ./test/) have all the other rules applied, but no-unused-expression only applies to files under ./src/.

answered Aug 1, 2019 at 10:45

Coderer's user avatar

CodererCoderer

24.9k27 gold badges93 silver badges142 bronze badges

Разрешение сообщений линтера документации

В этой теме описаны различные способы разрешения распространенных сообщений,которые выдает линтер документации.

Анатомия сообщения линтера документации

Это пример сообщения,выдаваемого линтером документации.

sample of a lint message

Линтерное сообщение документации содержит следующие элементы.Начиная с верхней строки:

  • Серьезность.Один из этих значков указывает на серьезность сообщения:
  • Сообщение правила стиля. Сообщение правила стиля в этом примере: Вы действительно имели в виду ‘sdfdsfsdfdfssd’? В нашем словаре его не было.
  • Ссылка на стиль. Некоторые ссылки связаны с разделом руководства по стилю, в котором объясняется правило. Ссылка на стиль в этом примере: Vale(Angular.Angular_Spelling) .
  • Расположение проблемного текста в документе определяется исходной строкой и столбцом как можно точнее. В некоторых сообщениях может не быть точного местоположения текста, вызвавшего сообщение. Расположение в этом примере: [Ln 8, Col 1] .
  • Файл определения теста стиля, создавший сообщение, связанное с файлом. Определение теста стиля в этом примере: Angular_Spelling.yml[Ln 1, Col 1]: View rule .

Стратегии улучшения документации

Эти советы помогут вам улучшить документацию и удалить сообщения об ошибках в документации.

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

Инструмент lint проверяет стили,содержащиеся в этих руководствах по стилю.Большинство тестов стиля включают ссылки на соответствующие разделы этих документов для получения дополнительной информации.

  • Руководство по стилю угловой документации
  • Руководство по стилю документации для разработчиков Google

Не каждый стиль,упомянутый в руководствах по стилю,имеет тест.Руководства по стилю и тесты стиля могут меняться.

Разделяйте длинные предложения

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

Подумайте о том,чтобы перестроить длинное предложение и разбить отдельные идеи на отдельные предложения или пункты.

Используйте списки и таблицы

Предложения,содержащие списки,разделенные запятыми,могут быть более понятными,если представить их в виде маркированного списка или таблицы.

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

Используйте более распространенные слова

Короткие,более распространенные слова обычно читаются легче,чем длинные.Это не означает,что вы должны писать,обращаясь к аудитории.Технические документы все равно должны быть точными.Документацию по Angular читает множество людей по всему миру,поэтому следует использовать язык,понятный большинству людей.

Если вы считаете,что определенный термин необходим,даже если он был отмечен как необычный,постарайтесь включить краткое объяснение этого термина.Также попробуйте добавить некоторый контекст вокруг его первого упоминания.

Ссылка термина на другой раздел или тему-это тоже вариант,но прежде чем использовать его,подумайте,не помешает ли это читателю.Если вы заставите читателя перейти на другую страницу за определением,он может потерять концентрацию на текущей теме и своей главной цели.

Используйте меньше слов

Если вы можете убрать слово и не потерять смысл предложения,оставьте его.

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

Подробнее о конкретных сообщениях линтера документации

Большинство сообщений по ссылке на документацию не требуют пояснений и содержат ссылку на дополнительную документацию.Некоторые сообщения определяют области,в которых документация может нуждаться в более тщательной проработке.Следующие типы сообщений часто встречаются в тех местах текста,которые следует пересмотреть и переписать,чтобы улучшить текст и убрать сообщение.

Слово too-wordy или должно быть заменено другим

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

Angular.WriteGood_TooWordy-Проверьте,сможете ли вы переписать предложение…

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

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

Too-wordy word Simpler replacement
accelerate speed up
accomplish perform, finish
acquire get
additional more
adjustment change
advantageous beneficial
consequently в результате
designate assign
equivalent the same
exclusively only
по большей части generally
имеют склонность к tend to
in addition furthermore
modify изменение или обновление
monitor observe
necessitate require
one particular one
момент времени moment
portion part
similar to like
validate verify
независимо от того whether

WordList messages

Сообщения о словах,обнаруженных этими стилевыми тестами,обычно предлагают лучшую альтернативу.Хотя слово,которое вы использовали,вероятно,было бы понято,оно,скорее всего,вызвало это сообщение по одной из следующих причин:

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

Proselint messages

Тесты стиля Proselint проверяют наличие слов,которые являются жаргонными или могут быть оскорбительными для некоторых людей.

Перепишите текст,заменив жаргонные или оскорбительные выражения на более инклюзивные.

Starting a sentence сообщения предложения

Некоторые слова, такие как so и there is/are , не обязательны в начале предложения. Предложения, которые начинаются со слов, обозначенных этим сообщением, обычно можно сделать короче, проще и яснее, переписав их без этих окончаний.

Cliches

Клише следует заменить более буквальным текстом.

Клише затрудняют понимание документации людьми,не понимающими английский язык.Когда клише переводятся онлайн-инструментами,такими как Google translate,они могут привести к запутанным результатам.

Если все остальное не помогает

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

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

Если вы используете эти исключения,пожалуйста,ограничьте объем текста,который вы исключаете из анализа,до минимально возможного количества строк.

При необходимости вы можете применить эти исключения к своему контенту.

  1. General exception

    Общее исключение позволяет исключить указанный текст из всех проверок на ворсинки.

    Чтобы применить общее исключение, окружите текст, который вы не хотите, чтобы линтер тестировал, элементами comment HTML , показанными в этом примере.

    
    Text the linter does not check for any style problem.
    
    

    Не забудьте оставить пустую строку перед и после каждого комментария.

  2. Style exception

    Исключение стиля позволяет исключить текст из отдельного теста стиля.

    Чтобы применить исключение стиля, окружите текст, который вы не хотите, чтобы линтер тестировал, этими элементами HTML- comment Между этими комментариями линтер игнорирует проверку стиля в комментарии, но по-прежнему проверяет все другие используемые стили.

    
    

    Замените Style.Rule в комментариях ссылкой на правило стиля из сообщения о проблеме, отображаемого в среде IDE. Например, представьте, что вы получили это сообщение о проблеме и хотите использовать слово, обозначенное как проблема.

    Did you really mean 
    Angular_Spelling.yml[Ln 1, Col 1]: View rule

    Style.Rule для этого сообщения — это текст в круглых скобках: Angular.Angular_Spelling данном случае Style.Rule Чтобы отключить этот тест стиля, используйте комментарии, показанные в этом примере. Angular.Angular_Spelling

    
    'inlines' does not display a problem because this text is not spell-checked.
    Remember that the linter does not check any spelling in this block of text.
    The linter continues to test all other style rules.
    
    


Angular

15.0

  • Руководства для разработчиков Angular

    Как фреймворк для приложений,Angular включает в себя коллекцию хорошо интегрированных библиотек,которые охватывают широкий спектр возможностей.

  • DevTools Overview

    Angular DevTools-это расширение для браузера,которое предоставляет возможности отладки и профилирования приложений.

  • Руководство по стилю угловой документации

    Это руководство по стилю охватывает стандарты написания документации по Angular angular.io.

  • Отображение части файла кода

    Чтобы включить фрагмент кода в образец файла, а не целиком, используйте атрибут региона <code-example>.

Поскольку JavaScript — это интерпретируемый язык, ошибки, допущенные в коде, выявляются во время его выполнения. Чтобы увидеть ошибки до запуска кода, используется инструмент, который называется линтер. Для поиска ошибок применяется статический анализ кода и используются особые правила.

Файл конфигурации eslint

Перед установкой расширения «ESLint» устанавливаем пакет eslint — локально (рекомендуется) или глобально (не рекомендуется). Расширение будет сначала искать локальный пакет, а в случае неудачи — глобальный.

$ npm install eslint --save-dev # локальная установка
$ npm install eslint --global # глобальная установка

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

$ npx eslint --init # если пакет установлен локально
$ eslint --init # если пакет установлен глобально
How would you like to use ESLint?
    To check syntax only
    To check syntax and find problems 
    To check syntax, find problems, and enforce code style
What type of modules does your project use?
    JavaScript modules (import/export) 
    CommonJS (require/exports)</li>
    None of these
Which framework does your project use?
    React
    Vue.js
    None of these 
Does your project use TypeScript? No / Yes
Where does your code run?
    Browser 
    Node.js 
What format do you want your config file to be in?
    JavaScript
    YAML
    JSON 

После этого будет создан json-файл конфигурации .eslintrc.json:

{
    "env": { // предоставляет предопределенные глобальные переменные
        "browser": true,
        "es2021": true,
        "node": true
    },
    "extends": "eslint:recommended", // рекомендуемый набор правил
    "parserOptions": {
        // версия синтаксиса ECMAScript: 5 (по умолчанию), 6 (или 2015), ..., 12 (2021), 13 (2022)
        "ecmaVersion": "latest",
        // script (значение по умолчанию) или module (если используются модули ECMAScript)
        "sourceType": "module"
    },
    "rules": {
        // можно переопределять recommended правила и добавлять правила, которых нет в recommended
    }
}

Если выбрать js-формат файла конфигурации — получим .eslintrc.js:

module.exports = {
    env: {
        browser: true,
        es2021: true,
        node: true,
    },
    extends: 'eslint:recommended',
    parserOptions: {
        ecmaVersion: 'latest',
        sourceType: 'module',
    },
    rules: {},
}

Рекомендуемый набор правил eslint:recommended выгллядит следующим образом:

{
    "constructor-super": "error", // проверка вызова super() в конструкторе
    "for-direction": "error", // проверка цикла for на конечное число итераций
    "getter-return": "error", // требовать return в getter
    "no-async-promise-executor": "error", // запрет async функции-исполнителя в Promise
    "no-case-declarations": "error", // запрет объявления переменных, функций и классов в case
    "no-class-assign": "error", // class A {} — запрет на приваивание нового значения A
    "no-compare-neg-zero": "error", // запрет на сравнение x === -0
    "no-cond-assign": "error", // запрет на присваивание в условиях
    "no-const-assign": "error", // запрет на изменение константы
    "no-constant-condition": "error", // запрет на константу в условии
    "no-control-regex": "error", // запрет на упр.символы в регулярках (ASCII от 0 до 31)
    "no-debugger": "error", // запрет на использование debugger
    "no-delete-var": "error", // запрет на использование delete с переменной
    "no-dupe-args": "error", // запрет одинаковых параметров в объявлений ф-ции
    "no-dupe-class-members": "error", // запрет повторяющихся членов класса
    "no-dupe-else-if": "error", // запрет повторяющихся условий в цепочках if-else-if
    "no-dupe-keys": "error", // запрет повторяющихся ключей в литералах объектов
    "no-duplicate-case": "error", // запрет повторяющихся значений case
    "no-empty": "error", // запрет пустых блоков кода — if(…) {пусто}
    "no-empty-character-class": "error", // запрет на пустые символьные классы [] в регулярках
    "no-empty-pattern": "error", // запрет пустых шаблонов деструктурирования let {} = foo
    "no-ex-assign": "error", // запрет переназначения err в catch — try {…} catch (err) {err = 1}
    "no-extra-boolean-cast": "error", // запрет лишних логических приведений — if (!!a) {…}
    "no-extra-semi": "error", // запрет лишних точек с запятой — let x = 5;;
    "no-fallthrough": "error", // запрет case без break и без комментария «fall through»
    "no-func-assign": "error", // запрет переназначения объявления function
    "no-global-assign": "error", // запрет переназначения глобальных переменных — window = {}
    "no-import-assign": "error", // запрет переназначения импорта — import a from …; a = 1
    "no-inner-declarations": "error", // запрет объявления ф-ций и переменных внутри блоков кода
    "no-invalid-regexp": "error", // запрет недопустимых строк регулярных выражений в RegExp()
    "no-irregular-whitespace": "error", // запрет неправильных пробельных символов
    "no-loss-of-precision": "error", // запрет литеральных чисел, которые теряют точность
    "no-misleading-character-class": "error", // запрет проблемных регулярных выражений
    "no-mixed-spaces-and-tabs": "error", // запрет смешанных отступов из пробелов и табуляций
    "no-new-symbol": "error", // запрет new Symbol()
    "no-nonoctal-decimal-escape": "error", // запрет 8 и 9 в строковых литералах
    "no-obj-calls": "error", // запрет вызова свойств глобального объекта как функций — Math()
    "no-octal": "error", // запрет восьмеричных литералов — x = 071 (теперь х равен 57)
    "no-prototype-builtins": "error", // запрет вызова некоторых методов прототипа на объекте
    "no-redeclare": "error", // запрет повторного объявления переменной
    "no-regex-spaces": "error", // запрет использования нескольких пробелов в регулярках
    "no-self-assign": "error", // запрет присваивания переменной самой себе — x = x
    "no-setter-return": "error", // // запрет на return в setter
    "no-shadow-restricted-names": "error", // запрет имен переменных и ф-ций типа NaN, undefined
    "no-sparse-arrays": "error", // запрет разреженных массивов
    "no-this-before-super": "error", // запрет в конструкторе использовать this до вызова super()
    "no-undef": "error", // запрет на использование необъявленных переменных
    "no-unexpected-multiline": "error", // запрет запутанных многострочных выражений
    "no-unreachable": "error", // запрет недостижимого кода после return, throw, continue и break
    "no-unsafe-finally": "error", // запрет return, throw, break и continue внутри блока finally
    "no-unsafe-negation": "error", // запрет отрицания левого операнда в операторах отношения
    "no-unsafe-optional-chaining": "error", // запрет использования foo?.bar в некоторых ситуациях
    "no-unused-labels": "error", // запрет неиспользуемых меток
    "no-unused-vars": "error", // запрет неиспользуемых переменных
    "no-useless-backreference": "error", // запрет бесполезных обратных ссылок в регулярках
    "no-useless-catch": "error", // запрет ненужных catch
    "no-useless-escape": "error", // запрет ненужных escape-символов
    "no-with": "error", // запрет использования with
    "require-yield": "error", // требовать yield для функции-генератора
    "use-isnan": "error", // требовать isNaN() для проверки NaN
    "valid-typeof": "error" // требовать для typeof допустимых строк "string", "undefined", "object"
}

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

{
    "env": {
        "browser": true,
        "es2021": true,
        "node": true
    },
    "extends": "eslint:recommended",
    "parserOptions": {
        "ecmaVersion": "latest",
        "sourceType": "module"
    },
    "rules": {
        "linebreak-style": ["error", "unix"], // символ(ы) конца строки
        "quotes": ["error", "single"], // использовать одинарные кавычки
        "semi": ["error", "never"], // точка с запятой в конце операторов
        "indent": ["error", 4, { "SwitchCase": 1 }], // отступы в коде из 4 пробелов с учетом switch...case
        "arrow-parens": ["error", "as-needed"], // скобки вокруг единственного параметра стрелочной функции
        "object-curly-spacing": ["error", "always"], // пробелы между скобками в литералах объектов
        "array-bracket-spacing": ["error", "never"], // пробелы между скобками в массивах
        "quote-props": ["error", "as-needed"], // свойства объекта в кавычках или без кавычек
        "no-trailing-spaces": "error", // не должно быть пробелов в конце строки
        "no-tabs": "error", // символы табуляции в коде запрещена везде
        "comma-dangle": ["error", { // запятая после последнего элемента массива или объекта
            "arrays": "always-multiline",
            "objects": "always-multiline",
            "imports": "never",
            "exports": "never",
            "functions": "never"
        }],
        "brace-style": ["error", "1tbs"], // правила для фигурных скобкок для блоков кода
        "keyword-spacing": "error", // пробел слева и справа для ключевых слов
        "no-multi-spaces": "error", // не допускается несколько пробелов подряд
        "eqeqeq": "error", // использовать === и !== вместо == и !=
        "camelcase": "error", // имена переменных и функций в стиле camelCase
        "max-len": ["error", 100], // максимальная длина строки
        "no-multiple-empty-lines": "error" // не больше 2 пустых строк подряд
    }
}

Внутри rules можно не только добавлять новые правила, но и переопределять правила, заданные в наборе eslint:recommended (или вовсе отключить некоторые правила установкой значения off).

ESLint будет искать файл конфигурации сначала в рабочей директории проекта, и далее — во всех родительских директориях вплоть до корневой. При этом директивы из первого найденного .eslintrc.json будут дополняться директивами из следующих найденных файлов. Если директивы противоречат друг другу, приоритет будет у того файла конфигурации, который был найден раньше. Поиск вверх по иерархии прекращается, когда найден файл конфигурации, содержащий настройку root в значении true. Так что мы можем использовать один файл конфигурации для всех проектов — только желательно добавить в него директиву root.

[projects]
    .eslintrc.json содержит {"root":true, …}
    [one-project]
       index.js
       package.json
       ..........
    [two-project]
       index.js
       package.json
       ..........

Файл конфигурации VS Code

Это файл settings.json, здесь нужно разрешить работу расширения и указать, какие файлы проверять и форматировать:

{
    ..........
    // По умолчанию форматирование кода запрещено
    "editor.formatOnSave": false, // форматировать код при сохранении файла
    "editor.formatOnPaste": false, // форматировать при вставке фрагмента кода
    "editor.codeActionsOnSave": [], // набор действий при сохранении файла
    "editor.defaultFormatter": null,
    // Разрешить или запретить расширения eslint и prettier
    "prettier.enable": true, // нужен рестарт vs code
    "eslint.enable": true,
    // Настройки форматирования javascript
    "eslint.format.enable": false, // запретить или разрешить форматирование
    "eslint.run": "onType", // запускать проверку кода по мере печати кода
    "eslint.probe": [ // какие файлы нужно проверять
        "javascript"
    ],
    "[javascript]": {
        // formatOnSave считается устаревшей, рекомендуется использовать codeActionsOnSave
        "editor.formatOnSave": false,
        "editor.formatOnPaste": true,
        "editor.codeActionsOnSave": [
            "source.formatDocument", // форматирование prettier
            "source.fixAll.eslint" // исправление ошибок eslint
        ],
        // "editor.defaultFormatter": "dbaeumer.vscode-eslint"
        "editor.defaultFormatter": "esbenp.prettier-vscode"
    },
    ..........
}

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

Но в примере выше расширение «ESLint» только проверяет код, а форматированием занимается расширение «Prettier» (см. здесь). Опция eslint.format.enable имеет значение false, а опция editor.defaultFormatter имеет значение esbenp.prettier-vscode. Форматирование у «ESLint» странное — например, в отличие от «Prettier», не выполняется разбиение длинных строк на две или три. Так что эту работу лучше оставить расширению «Prettier».

Проблема в том, что такая конфигурация толком не работает — расширения «ESLint» и «Prettier» для VS Code мешают друг другу.

Расширение «Prettier» не работает при сохранении, если editor.formatOnSave имеет значение false. То есть, «Prettier» вообще никак не реагирует на source.formatDocument — хотя в документации написано, что codeActionsOnSave заменяет и расширяет настройку formatOnSave.

С другой стороны, если выставить formatOnSave в true — перестает работать source.fixAll.eslint. Точнее говоря — внесенные «ESLint» изменения в код тут же затираются форматированием «Prettier» — formatOnSave срабатывает после codeActionsOnSave.

Можно форматировать (Alt+Shift+F) с использованием «Prettier». И можно исправить ошибки при сохранении (Ctrl+S) с использованием «ESLint». Возможно, причина этого в том, что VS Code активно развивается, постоянно добавляются новые возможности — и это просто временный баг, который пропадет при очередном обновлении.

Оказывается, есть расширение «Format Code Action» от Rohit Gohri для VS Code, которое позволяет решить эту проблему. После установки можно форматировать с использовием расширения «Prettier» по Alt+Shift+F. А при сохранении по Ctrl+S — сначала отработает форматирование «Prettier», а потом — исправление ошибок «ESLint». При этом «ESLint» будет затирать исправления «Prettier», если правила «ESLint» противоречат правилам «Prettier». Кроме того, можно изменить порядок запуска, если поменять местами элементы массива codeActionsOnSave.

Исходные коды здесь, директория eslint-prettier-together. Правила ESLint и Prettier имеют противоречия, так что видно, как одни исправления затирают другие. В принципе, если убрать противоречия, то такая конфигурация имеет право на жизнь. Но ниже мы рассмотрим более удачные способы подружить ESLint и Prettier.

ESLint и Prettier вместе, первый способ

У нас две проблемы. Первая — расширения «ESLint» и «Prettier» для VS Code мешают друг другу. Вторая — правила форматирования prettier могут противоречить правилам форматирования eslint. Давайте отредактируем файлы конфигурации .prettierrc и .eslintrc.json таким образом, чтобы спровоцировать такую ситуацию.

{
    "arrowParens": "avoid",
    "bracketSpacing": true,
    "endOfLine": "lf",
    "htmlWhitespaceSensitivity": "css",
    "insertPragma": false,
    "jsxBracketSameLine": false,
    "jsxSingleQuote": false,
    "printWidth": 80,
    "proseWrap": "preserve",
    "quoteProps": "as-needed",
    "requirePragma": false,
    "semi": false, // без точки с запятой в конце оператора
    "singleQuote": true,
    "tabWidth": 4,
    "trailingComma": "es5",
    "useTabs": false,
    "vueIndentScriptAndStyle": true,
    "embeddedLanguageFormatting": "auto"
}
{
    "env": {
        "browser": true,
        "es2021": true,
        "node": true
    },
    "extends": "eslint:recommended",
    "parserOptions": {
        "ecmaVersion": "latest",
        "sourceType": "module"
    },
    "rules": {
        "arrow-parens": ["error", "as-needed"],
        "object-curly-spacing": ["error", "always"],
        "array-bracket-spacing": ["error", "never"],
        "quote-props": ["error", "as-needed"],
        "semi": ["error", "always"], // точка с запятой в конце оператора
        "quotes": ["error", "single"],
        "linebreak-style": ["error", "unix"],
        "indent": ["error", 4, { "SwitchCase": 1 }],
        "no-trailing-spaces": "error",
        "no-tabs": "error",
        "comma-dangle": ["error", {
            "arrays": "always-multiline",
            "objects": "always-multiline",
            "imports": "never",
            "exports": "never",
            "functions": "never"
        }],
        "brace-style": ["error", "1tbs"],
        "keyword-spacing": "error",
        "no-multi-spaces": "off",
        "eqeqeq": "error",
        "camelcase": "error",
        "max-len": ["error", 100],
        "no-multiple-empty-lines": "error"
    }
}

После форматирования с использованием prettier (Alt+Shift+F) — получим множество сообщений «Missing semicolon» от eslint:

Чтобы скрестить ежа и ужа — установим пакет eslint-plugin-prettier, который позволит запускать prettier как правило eslint. Также потребуется установить пакет prettier — если он не был установлен ранее. То есть, мы вообще не будем использовать расширение VS Code «Prettier» при работе с js-файлами.

$ npm install prettier eslint-plugin-prettier --save-dev
{
    "devDependencies": {
        "eslint": "^8.20.0",
        "eslint-plugin-prettier": "^4.2.1",
        "prettier": "^2.7.1"
    }
}

Редактируем файл конфигурации .eslintrc.json:

{
    "root": true,
    "env": {
        "browser": true,
        "es2021": true,
        "node": true
    },
    "extends": [
        "eslint:recommended"
    ],
    "parserOptions": {
        "ecmaVersion": "latest",
        "sourceType": "module"
    },
    "plugins": ["prettier"],
    "rules": {
        "prettier/prettier": "error"
    }
}

Мы убрали из .eslintrc.json все правила, связанные с форматированием. Правила форматирования теперь только в .prettierrc — противоречий больше нет. И теперь это работает так — формально defaultFormatter теперь расширение «ESLint». Но фактически форматированием занимается prettier. Проблемы с форматированием будут подчеркнуты зеленой волнистой линией. А правила из eslint:recommended будут подчеркнуты оранжевой или красной волнистой линией.

{
    ..........
    // По умолчанию форматирование кода запрещено
    "editor.formatOnSave": false, // форматировать код при сохранении файла
    "editor.formatOnPaste": false, // форматировать при вставке фрагмента кода
    "editor.codeActionsOnSave": [], // набор действий при сохранении файла
    "editor.defaultFormatter": null,
    // Разрешить или запретить расширения eslint и prettier
    "prettier.enable": true, // нужен рестарт vs code
    "eslint.enable": true,
    // Настройки форматирования javascript
    "eslint.format.enable": true, // NEW запретить или разрешить форматирование
    "eslint.run": "onType", // запускать проверку кода по мере печати кода
    "eslint.probe": [ // какие файлы нужно проверять
        "javascript"
    ],
    "eslint.rules.customizations": [
        // для проблем форматирования кода уровень info
        {"rule": "prettier/prettier", "severity": "info"}
    ],
    "[javascript]": {
        // NEW устаревшая настройка editor.formatOnSave больше не нужна
        "editor.formatOnPaste": true,
        "editor.codeActionsOnSave": [
            "source.fixAll.eslint"
        ],
        "editor.defaultFormatter": "dbaeumer.vscode-eslint" // NEW форматирование eslint
    },
    ..........
}

Работает форматирование и исправление по сочетанию клавиш Alt+Shift+F + проверка кода по мере печати + форматирование и исправление при сохранении Ctrl+S. Теперь нет необходимости использовать устаревшую настройку formatOnSave. Впрочем, можно сделать и по старинке, с использованием formatOnSave.

{
    ..........
    // По умолчанию форматирование кода запрещено
    "editor.formatOnSave": false, // форматировать код при сохранении файла
    "editor.formatOnPaste": false, // форматировать при вставке фрагмента кода
    "editor.codeActionsOnSave": [], // набор действий при сохранении файла
    "editor.defaultFormatter": null,
    // Разрешить или запретить расширения eslint и prettier
    "prettier.enable": true, // нужен рестарт vs code
    "eslint.enable": true,
    // Настройки форматирования javascript
    "eslint.format.enable": true, // запретить или разрешить форматирование
    "eslint.run": "onType", // запускать проверку кода по мере печати кода
    "eslint.probe": [ // какие файлы нужно проверять
        "javascript"
    ],
    "eslint.rules.customizations": [
        // для проблем форматирования кода уровень info
        {"rule": "prettier/prettier", "severity": "info"}
    ],
    "[javascript]": {
        "editor.formatOnPaste": true,
        "editor.formatOnSave": true,
        "editor.defaultFormatter": "dbaeumer.vscode-eslint"
    },
    ..........
}

Цвет волнистой линии для подчеркивания можно задать в настройках VS Code settings.json

{
    ..........
    "workbench.colorCustomizations": {
        "editorError.foreground": "#FF0000",
        "editorWarning.foreground": "#FF9933",
        "editorInfo.foreground": "#00AA00",
    },
    ..........
}

Исходные коды здесь, директория eslint-prettier-together-one.

Для линтинга и форматирования typescript-кода нужно установить еще два пакета и внести изменения в eslintrc.json.

$ npm install @typescript-eslint/parser @typescript-eslint/eslint-plugin --save-dev
{
    "root": true,
    "env": {
        "browser": true,
        "es2021": true,
        "node": true
    },
    "extends": [
        "eslint:recommended",
        "plugin:@typescript-eslint/recommended"
    ],
    "parser": "@typescript-eslint/parser",
    "parserOptions": {
        "ecmaVersion": "latest",
        "sourceType": "module"
    },
    "plugins": [
        "@typescript-eslint",
        "prettier"
    ],
    "rules": {
        "prettier/prettier": "error"
    }
}
{
    ..........
    // По умолчанию форматирование кода запрещено
    "editor.formatOnSave": false, // форматировать код при сохранении файла
    "editor.formatOnPaste": false, // форматировать при вставке фрагмента кода
    "editor.codeActionsOnSave": [], // набор действий при сохранении файла
    "editor.defaultFormatter": null,
    // Разрешаем работу расширений prettier и eslint
    "prettier.enable": true, // разрешить работу расширения prettier (нужен рестарт vs code)
    "eslint.enable": true, // разрешить работу расширения eslint
    // Настройки prettier и eslint для файлов javascript, typescript и react
    "eslint.format.enable": true, // запретить или разрешить форматирование
    "eslint.run": "onType", // запускать проверку кода по мере печати кода
    "eslint.probe": ["javascript", "typescript"], // какие файлы нужно проверять
    "eslint.rules.customizations": [
        // для проблем форматирования кода уровень info
        {"rule": "prettier/prettier", "severity": "info"}
    ],
    "[javascript]": {
        "editor.formatOnPaste": true,
        "editor.formatOnSave": true,
        "editor.defaultFormatter": "dbaeumer.vscode-eslint",
    },
    "[javascriptreact]": {
        "editor.formatOnPaste": true,
        "editor.formatOnSave": true,
        "editor.defaultFormatter": "dbaeumer.vscode-eslint",
    },
    "[typescript]": {
        "editor.formatOnPaste": true,
        "editor.formatOnSave": true,
        "editor.defaultFormatter": "dbaeumer.vscode-eslint",
    },
    "[typescriptreact]": {
        "editor.formatOnPaste": true,
        "editor.formatOnSave": true,
        "editor.defaultFormatter": "dbaeumer.vscode-eslint",
    },
    ..........
}

Набор правил Standard

Кроме набора правил eslint:recommended есть еще несколько популярных наборов — Standard, Airbnb, Google и другие. Давайте для примера посмотрим, как использовать правила Standard — этот набор гораздо больше eslint:recommended и предупреждений об ошибках будет больше.

$ npm install eslint-config-standard eslint-plugin-promise eslint-plugin-import eslint-plugin-n --save-dev
{
    "devDependencies": {
        "eslint": "^8.20.0",
        "eslint-config-standard": "^17.0.0",
        "eslint-plugin-import": "^2.26.0",
        "eslint-plugin-n": "^15.2.4",
        "eslint-plugin-prettier": "^4.2.1",
        "eslint-plugin-promise": "^6.0.0",
        "prettier": "^2.7.1"
    }
}
{
    "root": true,
    "env": {
        "browser": true,
        "es2021": true,
        "node": true
    },
    "extends": [
        "standard"
    ],
    "parserOptions": {
        "ecmaVersion": "latest",
        "sourceType": "module"
    },
    "rules": {}
}

Standard включает в себя не только правила поиска ошибок, но и правила форматирования — так что мы опять упираемся в проблему противоречий с правилами prettier. Давайте установим модуль eslint-config-prettier, который отключит все правила, которые противоречат prettier.

$ npm install eslint-config-prettier --save-dev
{
    "devDependencies": {
        "eslint": "^8.20.0",
        "eslint-config-prettier": "^8.5.0",
        "eslint-config-standard": "^17.0.0",
        "eslint-plugin-import": "^2.26.0",
        "eslint-plugin-n": "^15.2.4",
        "eslint-plugin-prettier": "^4.2.1",
        "eslint-plugin-promise": "^6.0.0",
        "prettier": "^2.7.1"
    }
}
{   
    "root": true,
    "env": {
        "browser": true,
        "es2021": true,
        "node": true
    },
    "extends": [
        "standard",
        "plugin:prettier/recommended"
    ],
    "parserOptions": {
        "ecmaVersion": "latest",
        "sourceType": "module"
    },
    "rules": {}
}

Настройка plugin:prettier/recommended на самом деле делает следующее:

{
    "root": true,
    "env": {
        "browser": true,
        "es2021": true,
        "node": true
    },
    "extends": [
        "standard",
        "prettier"
    ],
    "parserOptions": {
        "ecmaVersion": "latest",
        "sourceType": "module"
    },
    "plugins": ["prettier"],
    "rules": {
        "prettier/prettier": "error",
        "arrow-body-style": "off",
        "prefer-arrow-callback": "off"
    }
}

Исходные коды здесь, директория eslint-prettier-standard-one.

Особенности конфигурации

Программисты обожают наводить тень на плетень — и разработчики ESLint не исключение. Два фрагмента ниже из файла конфигурации эквивалентны.

"plugins": [
    "react",       // npm module eslint-plugin-react
    "prettier"     // npm module eslint-plugin-prettier
]
"plugins": [
    "eslint-plugin-react",
    "eslint-plugin-prettier"
]

Еще запутаннее, когда имена плагинов начинаются с @ (пространство имен). Нужно учитывать, что @foo и @foo/bar находятся в одном пространстве имен, но это два разных плагина (npm-модуля). Два фрагмента ниже из файла конфигурации эквивалентны.

"plugins": [
    "@foo",               // npm module @foo/eslint-plugin
    "@foo/bar"            // npm module @foo/eslint-plugin-bar
]
"plugins": [
    "@foo/eslint-plugin",
    "@foo/eslint-plugin-bar"
]

И еще один важный момент — когда в extends используется префикс plugin:

"extends": [
    "plugin:foo/bar",
],

Это значит, что плагин eslint-plugin-foo содержит в себе набор правил bar:

// код плагина eslint-plugin-foo
module.exports = {
    configs: {
        bar: {
            plugins: ["foo"], // допускается foo вместо eslint-plugin-foo
            env: ["browser"],
            rules: {
                semi: "error",
                "foo/one": "error", // допускается foo вместо eslint-plugin-foo
                "foo/two": "error",
                "eslint-plugin-foo/three": "error",
            }
        },
        baz: {
            plugins: ["foo"], // допускается foo вместо eslint-plugin-foo
            env: ["node"],
            rules: {
                semi: "warn",
                "foo/one": "off", // допускается foo вместо eslint-plugin-foo
                "foo/two": "error",
                "eslint-plugin-foo/three": "off",
            }
        }
    }
};

Поиск:
IDE • JavaScript • Web-разработка • Конфигурация • Настройка • Плагин • Установка • Файл • ESLint • Prettier

Задание 3. Найдите ошибки

В этом репозитории находятся решение тестового задания «Найдите ошибки» для 16-й Школы разработки интерфейсов (зима 2020, Москва).

Инструменты

  • VS Code
  • VS Code debugger
  • console.log
  • Документация https://code.visualstudio.com/api/language-extensions/language-server-extension-guide

Найденные ошибки

1. Ошибки компиляции файла server.ts

Ошибка 1

В данном коде ошибка, textDocumentSync не может быть always:

conn.onInitialize((params: InitializeParams) => {
    return {
        capabilities: {
            textDocumentSync: 'always'
        }
    };
});

Смотрим возможные параметры и меняем на наиболее подходящее по смыслу:

conn.onInitialize((params: InitializeParams) => {
    return {
        capabilities: {
            textDocumentSync: TextDocumentSyncKind.Full
        }
    };
});

Ошибка 2

В данном коде ошибка, поле loc не существует у property.key

const validateProperty = (
    property: jsonToAst.AstProperty
): LinterProblem<RuleKeys>[] =>
    /^[A-Z]+$/.test(property.key.value)
        ? [
                {
                    key: RuleKeys.UppercaseNamesIsForbidden,
                    loc: property.key.loc
                }
            ]
        : [];

Идем в json-to-ast.d.ts, находим AstIdentifier и добавляем loc:

export interface AstIdentifier {
    type: 'Identifier';
    value: string;
    raw: string;
    loc: AstLocation;
}

2. Ошибки линтера

Запускаем дебаг расширения — ничего не работает при открытии json файла. Идем в настройки, включаем линтер — все еще не работает.

Включаем линтер по умолчанию

В принципе, это не ошибка, но для удобства дебага влючаем линтер сразу после запуска дебага расширения.

Идем в package.json, находим данную настройку:

"example.enable": {
    "type": "boolean",
    "default": false,
    "description": "Enable/disable example linter."
}

Меняем default на true:

"example.enable": {
    "type": "boolean",
    "default": true,
    "description": "Enable/disable example linter."
}

Правим линтер

Так как ничего не работает, то смотрим в Output для Language Server Example.

Находим там кучу стек трейсов вида:

For help, see: https://nodejs.org/en/docs/inspector
(node:19212) UnhandledPromiseRejectionWarning: SyntaxError: Unexpected symbol <f> at 1:1
1 | file://shri-2020-task-1/stub/pages/product.json
    ^
    at Object.<anonymous> (shri-2020-task-3node_modulesjson-to-astbuild.js:5:2)
    at Module._compile (internal/modules/cjs/loader.js:786:30)
    at Object..js (internal/modules/cjs/loader.js:798:10)
    at Module.load (internal/modules/cjs/loader.js:645:32)
    at Function._load (internal/modules/cjs/loader.js:560:12)
    at Module.require (internal/modules/cjs/loader.js:685:19)
    at require (internal/modules/cjs/helpers.js:16:16)
    at Object.<anonymous> (shri-2020-task-3outlinter.js:3:19)
(node:19212) UnhandledPromiseRejectionWarning: SyntaxError: Unexpected symbol <f> at 1:1

Открываем файл linter.js на 3 строке, видим, что это вызов функции makeLint. Смотрим, что передается в коде в эту функцию, находим в файле server.ts следующее:

const source = basename(textDocument.uri);
const json = textDocument.uri;

Передается путь до файла, вместо его содержимого, правим на следующее:

const source = basename(textDocument.uri);
const json = textDocument.getText();

Правим линтер 2

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

const errors: LinterProblem<TProblemKey>[] = [];
const ast: JsonAST = parseJson(json);

if (ast) {
    walk(ast, 
        (property: jsonToAst.AstProperty) => errors.concat(...validateProperty(property)), 
        (obj: jsonToAst.AstObject) => errors.concat(...validateObject(obj)));
}

Здесь используется contat, который возвращает новый массив, нам же надо добавлять в текущий массив, поэтому меняем на push.

const errors: LinterProblem<TProblemKey>[] = [];
const ast: JsonAST = parseJson(json);

if (ast) {
    walk(ast, 
        (property: jsonToAst.AstProperty) => errors.push(...validateProperty(property)), 
        (obj: jsonToAst.AstObject) => errors.push(...validateObject(obj)));
}

Правим линтер 3

Перезапускаем дебаг, линтер начинает успешно показывать ошибки (правда не всегда верно, к примеру есть много ошибок, что нужно поле block в объектах mods и elemMods).

Идем в настройки, пытаемся менять для каждого правила Severity.

Замечаем, что при установке уровня Error ставится уровень Information. Находим в коде место с ошибкой:

function GetSeverity(key: RuleKeys): DiagnosticSeverity | undefined {
    if (!conf || !conf.severity) {
        return undefined;
    }

    const severity: Severity = conf.severity[key];

    switch (severity) {
        case Severity.Error:
            return DiagnosticSeverity.Information;

Правим кусок со switch на

switch (severity) {
    case Severity.Error:
        return DiagnosticSeverity.Error;

Правим линтер 4

Замечаем, что если поправить ошибку, то сообщение о ней не исчезает.
Пролема в этом куске кода, который посылает новый массив ошибок, только если он не пустой.

if (diagnostics.length) {
    conn.sendDiagnostics({ uri: textDocument.uri, diagnostics });
}

Меняем данный код на

conn.sendDiagnostics({ uri: textDocument.uri, diagnostics });

Так как будем подключать свой линтер, то не правим текущую реализацию правил. Считаем, что все ошибки, мешающие работе линтера, исправлены.

3. Ошибки превью

Ошибка regexp

Открываем превью, вместо него наблюдаем {{content}}. Ищем по слову content в коде, обнаруживаем файл previewindex.html и код, который по всей видимости должен подключать наш html:

panel.webview.html = previewHtml 
                .replace(/{{s+(w+)s+}}/g, (str, key) => {
                    switch (key) {
                        case 'content':
                            return html;
                        case 'mediaPath':
                            return getMediaPath(context);
                        default:
                            return str;
                    }
                });

Решаем, что хочется, чтобы код одинаково обрабатывал случаи {{content}} и {{ content }}, поэтому меняем regexp на:

panel.webview.html = previewHtml 
                .replace(/{{s*(w+)s*}}/g, (str, key) => {

Ошибка стилей

Перезапускаем дебаг, {{content}} пропадает, остается пустое поле. Пытаемся посмотреть, через VS Code Developer Tools что внутри, но это не дает дополнительной информации.

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

.div {
    ...
}

.div::before {
    ...
}

Вместо селекторов по тегам, используется селектор по именам классов, правим код на следующий:

div {
    ...
}

div::before {
    ...
}

Ошибка подключения стилей

Перезапускаем дебаг расширения — все равно ничего не появляется. Появляется предположение, что проблема в подключении стилей.
Вставляем стили напрямую в index.html в тег style.

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

Ошибка CSP

Копаем дальше, в чем проблема.

Обнаруживаем в Output > Log (Extension Host) следующую ошибку:

[2020-01-12 19:33:09.479] [exthost] [warning] undefined_publisher.shri-ext created a webview without a content security policy: https://aka.ms/vscode-webview-missing-csp

Идем по ссылке, и обнаруживаем, что для подключения своих стилей скриптов надо вставить в html следующую строку.

<meta
  http-equiv="Content-Security-Policy"
  content="default-src 'none'; script-src ${webview.cspSource}; style-src ${webview.cspSource};"
/>

Подключаем ее, но это не помогает (но ошибка из консоли исчезает).

Ошибка подключения стилей 2

Продолжаем попытки поключить наши стили. Находим официальный пример расширения с webview https://github.com/microsoft/vscode-extension-samples/blob/master/webview-sample/src/extension.ts#L164 . Понимаем, что для пути нужно использовать функцию webview.asWebviewUri.

Меняем функцию для отрисовки webview:

const mediaPath = panel.webview.asWebviewUri(getMediaPath(context)).toString();

panel.webview.html = previewHtml 
    .replace(/{{s*(w+)s*}}/g, (str, key) => {
        switch (key) {
            case 'cspSource':
                return panel.webview.cspSource;
            case 'content':
                return html;
            case 'mediaPath':
                return mediaPath;
            default:
                return str;
        }
    });

и меняем фунцию getMediaPath на:

const getMediaPath = (context: vscode.ExtensionContext) => vscode.Uri
    .file(context.asAbsolutePath("/"));

Перезапускаем дебаг расширения, в результате все работает.

Добавляем возможность подключения скриптов

Добавляем на будущее возможно подключения script.js в index.html:

<body>
    {{content}}
    <script src="./preview/script.js"></script>
</body>

Запрещаем команду не в json файлах

Замечаем, что команда Example: Show preview из палитры команд запускается на любых файлах (не только json). Меняем настройки, чтобы ограничиться json:

"commands": [
    {
        "command": "example.showPreviewToSide",
        "title": "Show preview",
        "category": "Example",
        "enablement": "editorLangId == json",
        "icon": {
            "light": "./media/PreviewIcon16x.svg",
            "dark": "./media/PreviewIcon16x_dark.svg"
        }
    }
],

4. Добавление линтера и превью из заданий 1 и 2

Для превью просто заменяем файлы в папке preview.

Для линтера были скопированы файлы из 2 задания. В идеале нужно опубликовать линтер как отдельный пакет и использовать уже пакет.

Для линтера была добавлена поддержка настроек по каждому правилу. Так как добавление вручную настроек в package.json чревато случайными ошибками, то была создана дополнительная утилита для автоматической генерации секции contributes.configuration файла package.json.

Для запуска утилиты используется команда npm run update-package-json-config.

5. Стилистические проблемы

Неиспользуемые файлы

Файлы jsonMain.ts и hash.ts не выполняют какие-то полезные нужные действия. Поэтому лучше эти файлы удалить.

Свои .d.ts файлы

Не всегда нужно писать свои .d.ts файлы для js библиотек. Для многих уже есть готовые типы в пакетах вида @types/*. К примеру для библиотеки json-to-ast есть пакет с типами @types/json-to-ast.

Отсутствие code style

Различные стили импорта

В коде используются разные виды импорта:

import * as vscode from 'vscode';
import {
    LanguageClient,
    LanguageClientOptions,
    ServerOptions,
    TransportKind,
    SettingMonitor,
    DocumentColorRequest
} from 'vscode-languageclient';

Лучше придерживаться одного стиля (если это конечно не реакт, там импорт React для jsx оправдан).

Различное именование

Есть как функции с именами в стиле PascalCase, так и в стиле camelCase. Лучше придерживаться единого стиля.

Различные стили функции на верхнем уровне

Есть как обычные функции (к примеру activate), так и стрелочные функции (openPreview). Лучше придерживаться единого стиля.

Понравилась статья? Поделить с друзьями:
  • Как исправить ошибки когда делаешь пропуск на мкад
  • Как исправить ошибки загрузочного сектора
  • Как исправить ошибки драйверов виндовс 10
  • Как исправить ошибки длл файлов
  • Как исправить ошибки виндовс 7 программа