VS Code: создание расширений

Расширение VS Code — Node.js модуль с TypeScript API, добавляющий в редактор команды, языковые возможности, UI-элементы или интеграцию с внешними сервисами.

Зачем нужно

Если существующие расширения не покрывают конкретную задачу — можно написать своё. Это полезно для автоматизации внутренних инструментов компании, кастомных сниппетов с логикой, интеграции с проприетарными системами или публикации open source инструмента.

Где используется

  • Внутренние инструменты команды (кодогенерация, шаблоны)
  • Языковая поддержка для DSL или специфических форматов
  • Интеграция с системами управления задачами (Jira, Linear)
  • Open source расширения для Marketplace

Быстрый старт

# Установка yeoman генератора
npm install -g yo generator-code

# Создание заготовки расширения
yo code

# Выбрать: New Extension (TypeScript)
# Название: my-extension
# Идентификатор: my-extension

Структура расширения

my-extension/
  src/
    extension.ts    — точка входа (activate/deactivate)
  package.json      — манифест расширения
  tsconfig.json
  .vscode/
    launch.json()     — конфигурация отладки расширения

package.json расширения

{
  "name": "my-extension",
  "displayName": "My Extension",
  "description": "Что делает расширение",
  "version": "0.1.0",
  "engines": { "vscode": "^1.85.0" },
  "categories": ["Other"],
  "activationEvents": ,
  "main": "./out/extension.js",
  "contributes": {
    "commands": [
      {
        "command": "myExtension.generateComponent",
        "title": "Generate React Component"
      }
    ],
    "menus": {
      "explorer/context": [
        {
          "command": "myExtension.generateComponent",
          "when": "explorerResourceIsFolder"
        }
      ]
    },
    "keybindings": [
      {
        "command": "myExtension.generateComponent",
        "key": "ctrl+shift+g"
      }
    ]
  }
}

extension.ts — основная логика

import * as vscode from 'vscode';
import * as fs from 'fs';
import * as path from 'path';

export function activate(context: vscode.ExtensionContext) {
  console.log('Extension "my-extension" is now active');

  // Регистрация команды
  const command = vscode.commands.registerCommand(
    'myExtension.generateComponent',
    async (uri: vscode.Uri) => {
      // Запрос имени у пользователя
      const name = await vscode.window.showInputBox({
        prompt: 'Имя компонента',
        placeHolder: 'Button',
        validateInput: (v) => /^[A-Z][a-zA-Z]+$/.test(v) ? null : 'PascalCase',
      });

      if (!name) return;

      // Создаём файл компонента
      const folderPath = uri.fsPath;
      const filePath = path.join(folderPath, `${name}.tsx`);
      const content = generateComponent(name);

      fs.writeFileSync(filePath, content, 'utf8');

      // Открываем созданный файл
      const doc = await vscode.workspace.openTextDocument(filePath);
      await vscode.window.showTextDocument(doc);

      vscode.window.showInformationMessage(`Компонент ${name} создан`);
    }
  );

  context.subscriptions.push(command);
}

function generateComponent(name: string): string {
  return `import React from 'react';\n\nexport function ${name} {\n  return <div>${name}</div>;\n}\n`;
}

export function deactivate() {}

Отладка расширения

F5 в папке расширения — открывает Extension Development Host
Все изменения → Ctrl+R в Extension Host для перезагрузки
Ctrl+Shift+P → выбрать свою команду для тестирования

Публикация

npm install -g @vscode/vsce

# Сборка .vsix для локальной установки
vsce package

# Публикация в Marketplace (нужен Azure DevOps Personal Access Token)
vsce publish

Частые ошибки

  • Не регистрируют команду в contributes.commands package.json — она не видна в UI
  • Не возвращают Disposable из subscriptions — утечка памяти при деактивации
  • activate вызывается при каждом открытии редактора — тяжёлая инициализация замедляет старт
  • Нет deactivate — ресурсы не освобождаются при отключении расширения

Связанные темы

Ресурсы