Создание простого инструмента проверки стиля кода
Создайте пользовательский диагностический инструмент с помощью API компилятора
«Создание простого инструмента проверки стиля кода» — бесплатный урок TypeScript Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения TypeScript Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс TypeScript Academy содержит 4 уроков всего.
Что такое инструмент линтинга
Инструмент линтинга анализирует исходный код и сообщает о проблемах со стилем или корректностью. Использование API компилятора TypeScript позволяет создавать правила, учитывающие типы, чего плагины ESLint не могут достичь самостоятельно.
// Goal: warn when console.log is called in TypeScript filesНастройка проекта
Создайте скрипт Node.js, который загружает программу TypeScript, обходит AST и сообщает о диагностике.
import ts from "typescript";
import path from "path";
const files = ["src/index.ts"];
const program = ts.createProgram(files, { strict: true });Определение правила
Правило — это функция, которая получает узел AST и возвращает необязательное диагностическое сообщение, если правило нарушено.
type Diagnostic = { file: string; line: number; message: string };
function noConsoleLog(node: ts.Node, sf: ts.SourceFile): Diagnostic | null {
if (!ts.isCallExpression(node)) return null;
const expr = node.expression.getText(sf);
if (expr !== "console.log") return null;
const { line } = sf.getLineAndCharacterOfPosition(node.pos);
return { file: sf.fileName, line: line + 1, message: "No console.log allowed" };
}Обход AST
Напишите рекурсивный обход, применяющий все правила к каждому узлу в каждом исходном файле.
function walk(
node: ts.Node,
sf: ts.SourceFile,
rules: ((n: ts.Node, sf: ts.SourceFile) => Diagnostic | null)[]
): Diagnostic[] {
const diags: Diagnostic[] = [];
for (const rule of rules) {
const d = rule(node, sf);
if (d) diags.push(d);
}
ts.forEachChild(node, child => diags.push(...walk(child, sf, rules)));
return diags;
}Запуск линтера
Переберите все исходные файлы, примените правила и выведите диагностику.
const rules = [noConsoleLog];
const allDiagnostics: Diagnostic[] = [];
for (const sf of program.getSourceFiles()) {
if (!sf.isDeclarationFile) {
allDiagnostics.push(...walk(sf, sf, rules));
}
}
allDiagnostics.forEach(d =>
console.log(`${d.file}:${d.line} — ${d.message}`)
);Добавление правила с учётом типов
Используйте проверяющий типы, чтобы создавать правила, зависящие от типа TypeScript выражения.
const checker = program.getTypeChecker();
function noAnyReturn(node: ts.Node, sf: ts.SourceFile): Diagnostic | null {
if (!ts.isFunctionDeclaration(node)) return null;
const sig = checker.getSignatureFromDeclaration(node);
if (!sig) return null;
const ret = checker.getReturnTypeOfSignature(sig);
if (ret.flags & ts.TypeFlags.Any) {
const { line } = sf.getLineAndCharacterOfPosition(node.pos);
return { file: sf.fileName, line: line + 1, message: "Function returns any" };
}
return null;
}Код завершения для CI
Возвращайте ненулевой код завершения, если найдена диагностика, чтобы конвейеры CI могли завершить сборку с ошибкой.
if (allDiagnostics.length > 0) {
console.error(`${allDiagnostics.length} lint error(s)`);
process.exit(1);
}
process.exit(0);Правило: отсутствие неиспользуемых переменных
API компилятора предоставляет диагностику неиспользуемых переменных через ts.getPreEmitDiagnostics, дополняя пользовательские правила встроенными проверками.
const preEmit = ts.getPreEmitDiagnostics(program);
preEmit.forEach(d => {
const msg = ts.flattenDiagnosticMessageText(d.messageText, "
");
console.log(msg);
});Правило: требовать типы возврата
Правило, предупреждающее об отсутствии явных аннотаций типа возврата у функций, помогает поддерживать дисциплину документирования.
function requireReturnType(node: ts.Node, sf: ts.SourceFile): Diagnostic | null {
if (!ts.isFunctionDeclaration(node)) return null;
if (!node.type) {
const { line } = sf.getLineAndCharacterOfPosition(node.pos);
return { file: sf.fileName, line: line + 1, message: "Missing return type" };
}
return null;
}Сравнение с ESLint
Ваш пользовательский линтер дополняет ESLint. Используйте ESLint для правил стиля, а инструмент на основе API компилятора TypeScript — для правил, учитывающих типы и недоступных в ESLint.
// ESLint: stylistic and common pattern rules
// Compiler API linter: deep type reasoning, custom constraintsИтоги: создание линтера
Линтер на основе API компилятора TypeScript создаёт программу, обходит AST с правилами, при необходимости запрашивает проверяющий типы и завершает работу с ненулевым кодом при наличии ошибок. Такой подход позволяет создавать правила линтинга, действительно учитывающие типы.
Быстрая проверка
Что даёт линтеру на основе API компилятора преимущество перед ESLint?
Что Вы узнали
Вы создали простой линтер TypeScript с использованием API компилятора: загрузили программу, обошли AST, применили правила (при необходимости учитывающие типы) и сообщили о диагностике. Это основа пользовательского статического анализа в любом проекте TypeScript.
Изучай TypeScript с ИИ-репетитором — бесплатно
Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.
- Курсы
- 101
- Уроки
- 352
Часто задаваемые вопросы
Урок «Создание простого инструмента проверки стиля кода» бесплатный?
Да — полный текст урока «Создание простого инструмента проверки стиля кода» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс TypeScript Academy, подпишись на CoddyKit PRO. Курс TypeScript Academy содержит 4 уроков всего.
Чему я научусь в уроке «Создание простого инструмента проверки стиля кода»?
Создайте пользовательский диагностический инструмент с помощью API компилятора Ты практикуешь TypeScript Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать TypeScript Academy?
Предыдущий опыт не требуется. TypeScript Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.
Сколько времени занимает урок «Создание простого инструмента проверки стиля кода»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке TypeScript Academy?
Да. Каждый урок TypeScript Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Создание программы TypeScript с помощью API
- Обход AST с помощью посетителей
- Пользовательские преобразователи и генерация кода
- Создание простого инструмента проверки стиля кода