Обработка ошибок компиляции

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

Внутри SWC ядро написано на Rust, и ошибки представлены как строго типизированные структуры. Каждая диагностическая запись включает:

  • код ошибки (error code)
  • человекочитаемое сообщение
  • уровень критичности (fatal / error / warning)
  • диапазон в исходном коде (span)
  • контекст файла (source file)
  • дополнительные метаданные трансформации

Такой подход позволяет разделять этапы обнаружения проблемы: парсинг, трансформация AST, генерация кода и интеграционные фазы (например, работа через CLI или API).

Диагностическая модель отделена от логики компилятора, что делает ошибки предсказуемыми и сериализуемыми для внешних инструментов (bundler’ов, IDE и сборочных систем).

Ошибки парсинга и лексического анализа

На раннем этапе компиляции — в swc_ecma_parser — фиксируются синтаксические и лексические ошибки. Это наиболее частый класс проблем, возникающих при обработке JavaScript и TypeScript.

Типовые категории:

Лексические ошибки

Возникают при невозможности токенизации входного потока:

  • некорректные символы Unicode
  • незакрытые строковые литералы
  • ошибки escape-последовательностей

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

Синтаксические ошибки

Обнаруживаются при построении AST:

  • пропущенные скобки
  • неверная структура выражений
  • некорректные конструкции языка (например, недопустимые комбинации await вне async-контекста)
  • ошибки JSX-разметки

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

Механизм span и привязка к исходному коду

Ключевой механизм диагностики — система Span. Каждый узел AST и каждая ошибка связаны с диапазоном символов исходного файла.

Span содержит:

  • начало (byte offset)
  • конец (byte offset)
  • опционально: позиции строк и колонок

Эта модель позволяет:

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

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

Ошибки TypeScript и JSX

При включении поддержки TypeScript (swc_ecma_parser с TS-флагами) добавляется дополнительный слой диагностики.

TypeScript-ошибки на уровне синтаксиса

SWC не выполняет полноценную типовую проверку, но фиксирует структурные ошибки:

  • неверные generic-конструкции
  • ошибки интерфейсов и деклараций
  • некорректные модификаторы доступа
  • нарушение структуры enum или namespace

Важно, что SWC отделяет синтаксический анализ TS от семантической типизации, оставляя последнюю внешним инструментам (например, TypeScript compiler API).

JSX-диагностика

Ошибки JSX включают:

  • некорректное вложение тегов
  • отсутствие закрывающих элементов
  • ошибки в выражениях внутри {}

JSX анализируется как расширение грамматики JavaScript, и ошибки здесь часто пересекаются с синтаксическими ошибками общего парсера.

Ошибки трансформации AST

После успешного построения AST начинается этап трансформаций (swc_ecma_transforms). Здесь ошибки имеют иной характер: они уже не синтаксические, а логические или структурные.

Категории ошибок трансформации:

Некорректные входные узлы

Трансформеры ожидают строго определённые формы AST. Если узел повреждён или не соответствует ожидаемому паттерну, фиксируется ошибка трансформации.

Ошибки плагинов

SWC поддерживает plugin-based архитектуру (через WASM или внешние расширения). Ошибки здесь могут включать:

  • несоответствие версии AST
  • нарушение контракта входных/выходных структур
  • panic в пользовательском трансформере (в Rust-реализации это часто конвертируется в диагностический error boundary)

Ошибки оптимизаций

При включении оптимизирующих проходов:

  • dead code elimination может столкнуться с неконсистентными графами
  • inlining функций может провоцировать некорректные ссылки на span
  • минификация иногда выявляет недопустимые конструкции, ранее не критичные

Fatal и recoverable ошибки

Диагностическая система SWC разделяет ошибки по степени критичности.

Fatal errors

Полностью прерывают компиляцию:

  • синтаксические ошибки
  • невозможность построения AST
  • критические сбои трансформаций

Recoverable errors

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

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

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

Агрегация ошибок

SWC способен собирать множественные ошибки за один проход. Вместо остановки на первой найденной проблеме компилятор может:

  • продолжить парсинг после восстановления контекста
  • накопить список диагностик
  • вернуть их единым структурированным объектом

Этот механизм реализуется через error recovery стратегии в парсере. Они позволяют пропускать повреждённые участки кода и продолжать анализ следующих токенов.

Интеграция с Source Map

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

SWC:

  • сохраняет оригинальные span до трансформации
  • связывает их с выходными позициями
  • позволяет IDE отображать ошибки в исходных файлах TypeScript/JavaScript

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

Ошибки в CLI и API

При использовании SWC через CLI или @swc/core API добавляется дополнительный слой ошибок:

CLI ошибки

  • неверные аргументы командной строки
  • отсутствие входных файлов
  • конфликты конфигурации .swcrc

API ошибки

  • некорректная конфигурация transform/bundle функций
  • несовместимость опций (например, включение взаимоисключающих пресетов)
  • ошибки сериализации AST между JS и Rust слоем

В Node.js биндингах ошибки часто оборачиваются в стандартные Error объекты, но с расширенными полями диагностики.

Формат диагностических сообщений

Типичная ошибка SWC включает:

  • код (например, E1001)
  • текстовое сообщение
  • span с диапазоном
  • дополнительную информацию о контексте

Сообщения формируются на уровне Rust ядра и затем сериализуются в формат, удобный для JavaScript окружения.

Поведение при частичной компиляции

SWC часто используется в сборочных системах (Next.js, Vite-плагины через интеграции). В таких сценариях ошибки обрабатываются по стратегии:

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

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

Ошибки в incremental pipelines

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

  • инвалидировать кеш при изменении исходного кода
  • обновлять span-диапазоны при повторном парсинге
  • пересчитывать diagnostics при частичной пересборке

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

Особенности деградации при сбоях

SWC стремится сохранять максимальную устойчивость пайплайна:

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

Такая модель позволяет использовать компилятор в production-сборках без полной остановки пайплайна при единичных ошибках модулей