Диагностические сообщения: структура и коды

Общая концепция диагностической системы

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

Ключевая особенность системы заключается в разделении:

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

Такой подход позволяет отделить логику формирования ошибки от её представления пользователю.


Базовая структура диагностического сообщения

Каждое диагностическое сообщение в Parcel представляет собой объект с фиксированным набором полей. Несмотря на расширяемость, существует ядро структуры, которое присутствует практически всегда.

Основные поля

type Diagnostic = {
  message: string,
  code?: string,
  severity: 'error' | 'warning' | 'info',
  origin?: string,
  filePath?: string,
  language?: string,
  stack?: string,
  hints?: Array<string | DiagnosticHint>,
  documentationURL?: string,
  name?: string,
  diagnosticCode?: number
};

Смысл ключевых полей

message

Человеко-читаемое описание проблемы. Это основное содержимое, которое выводится в консоль или интерфейс IDE.

severity

Определяет критичность:

  • error — блокирует сборку
  • warning — не блокирует, но требует внимания
  • info — информационное сообщение

code

Строковый идентификатор категории ошибки. Используется для группировки и быстрого поиска причин.

Примеры:

  • BABEL_TRANSFORM_ERROR
  • RESOLVE_FAILED
  • FS_MODULE_NOT_FOUND

Диагностические коды и их назначение

Система кодов в Parcel служит нескольким целям:

  1. Стабильная идентификация ошибки
  2. Межплагинная совместимость
  3. Локализация и документация
  4. Фильтрация сообщений в инструментах разработчика

Структура кода

Код обычно представляет собой строку в формате:

<DOMAIN>_<COMPONENT>_<TYPE>

Примеры доменов

  • RESOLVE — ошибки резолва модулей
  • TRANSFORM — ошибки трансформации кода
  • FS — файловая система
  • CACHE — кэширование
  • OPTIMIZER — оптимизация бандла

Примеры кодов

  • RESOLVE_MODULE_NOT_FOUND
  • TRANSFORM_SYNTAX_ERROR
  • FS_INVALID_PATH
  • CACHE_WRITE_FAILED

Структура контекста ошибки (location model)

Одним из ключевых компонентов диагностики является точное указание места возникновения проблемы.

Базовая структура location

type DiagnosticLocation = {
  filePath: string,
  start: {
    line: number,
    column: number
  },
  end?: {
    line: number,
    column: number
  }
};

Дополнительный контекст

Parcel может расширять location следующими данными:

  • фрагмент исходного кода (code frame)
  • указатель на строку с ошибкой
  • диапазон выделения
  • вложенные источники (например, трансформированный код)

Code frame: визуализация ошибки

Code frame — это текстовое представление участка кода с подсветкой ошибки.

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

  10 | const a = 10;
  11 | const b = a();
                ^
  12 | console.log(b);

Особенности формирования

  • автоматически расширяется вокруг строки ошибки
  • учитывает sourcemaps
  • поддерживает вложенные трансформации (Babel, TypeScript и др.)
  • нормализует табуляцию и пробелы

Hints: система подсказок

Поле hints содержит дополнительные рекомендации для исправления ошибки.

Структура hint

type DiagnosticHint = {
  message: string,
  language?: 'text' | 'markdown',
  code?: string
};

Примеры использования hints

  • предложение установить зависимость
  • подсказка о неправильном импорте
  • рекомендация обновить конфигурацию
  • указание на альтернативный синтаксис

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


Severity и правила приоритизации

Parcel использует строгую модель приоритетов:

  1. error — прерывает сборку
  2. warning — отображается, но не блокирует
  3. info — логическая информация о процессе

Влияние severity на pipeline

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

Origin: источник диагностического сообщения

Поле origin определяет компонент, породивший сообщение.

Типичные значения origin

  • parcel
  • @parcel/resolver-default
  • @parcel/transformer-babel
  • @parcel/optimizer-terser
  • сторонние плагины

Назначение origin

  • трассировка источника ошибки
  • фильтрация сообщений по плагинам
  • отладка пользовательских расширений

Числовые диагностические коды (legacy/compat layer)

Помимо строковых кодов, Parcel поддерживает числовые идентификаторы:

diagnosticCode?: number

Причины существования

  • совместимость со старыми инструментами
  • ускоренный индекс поиска ошибок
  • интеграция с telemetry системами

Особенности

  • не являются основным источником идентификации
  • могут изменяться между версиями
  • не гарантируют стабильность API

Stack trace и его роль в диагностике

Поле stack содержит стек вызовов, приведший к ошибке.

Особенности обработки

  • нормализуется Parcel runtime
  • может содержать смешанные фреймы (JS + трансформированный код)
  • фильтруется от внутренних служебных вызовов

Типичная структура

Error: Unexpected token
  at transform (babel-transformer)
  at parse (parser)
  at loadModule (resolver)

Группировка диагностических сообщений

Parcel агрегирует сообщения по нескольким признакам:

  • code
  • filePath
  • origin
  • dependency graph node

Преимущества группировки

  • уменьшение шума в CLI
  • предотвращение дублирования ошибок
  • улучшение UX в больших проектах

Форматирование в CLI

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

  • цветовое выделение severity
  • подсветка кода
  • сокращение путей
  • группировка по модулям

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

? RESOLVE_MODULE_NOT_FOUND

Cannot find module 'react'

  /src/index.js:1:17

> 1 | import React from 'react';
                  ^^^^^^^^^^^^

Hint: Install package 'react' using npm or yarn.

Взаимодействие диагностики с sourcemaps

Sourcemaps играют ключевую роль в точности диагностических сообщений.

Использование sourcemaps позволяет:

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

Проблемные случаи

  • отсутствующие sourcemaps
  • частично повреждённые maps
  • несовпадение версий трансформеров

Диагностика в плагинной системе

Плагины Parcel могут генерировать собственные диагностические сообщения.

Рекомендованная структура для плагинов

  • использовать уникальный origin
  • задавать стабильные code
  • включать контекст через filePath и location
  • добавлять actionable hints

Пример сценария

  • плагин обнаруживает некорректный конфиг
  • формирует Diagnostic
  • возвращает его в pipeline
  • Parcel агрегирует и отображает

Нормализация и сериализация диагностических объектов

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

  • удаляются циклические ссылки
  • нормализуются пути
  • конвертируются сложные структуры location
  • приводятся типы к JSON-safe формату

Роль диагностических кодов в автоматизации

Диагностические коды используются для:

  • написания автокорректоров
  • генерации документации
  • построения систем подсказок в IDE
  • аналитики частоты ошибок

Расширяемость модели диагностики

Архитектура Parcel допускает расширение структуры Diagnostic без нарушения обратной совместимости.

Возможные расширения:

  • дополнительные метаданные (tags)
  • structured suggestions (actions)
  • links на external resources
  • telemetry hooks
  • machine-readable fix instructions