iducationducation
IndexArticlesFormationsProfilOutilsBibliothech
N°014 — 2026
Navigation
01Index02Articles03Formations04Profil05Outils06Bibliothech
N°014 — 2026
iducationducation
IndexArticlesFormationsProfilOutilsBibliothech
N°014 — 2026
Navigation
01Index02Articles03Formations04Profil05Outils06Bibliothech
N°014 — 2026
Formations
TypeScript · Intermédiaire

Extensions VS Code

Utiliser, créer et publier une extension VS Code en TypeScript : commandes, configuration, vues, webviews, diagnostics, tests, bundling et publication sur le Marketplace et Open VSX.

VS Code APITypeScriptesbuildvsceOpen VSXGitHub Actions
01Utiliser et gérer ses extensions02Générer et lancer sa première extension03Commandes, réglages et activation04Barre d'état, vues et décorations05Webviews : un panneau HTML dans l'éditeur06Diagnostics, corrections rapides et complétion07Tester et bundler l'extension08Publier sur le Marketplace et Open VSX
Chapitre 2·25 min

Générer et lancer sa première extension

Microsoft maintient un générateur officiel, generator-code, basé sur Yeoman. Il produit un projet TypeScript prêt à déboguer. On l'utilise une fois, puis on comprend chaque fichier qu'il a créé.

Générer le projet

Il faut Node.js (version LTS) et Git. Pas besoin d'installer le générateur globalement :

npx --package yo --package generator-code -- yo code

Les réponses pour TODO Radar :

? What type of extension do you want to create? New Extension (TypeScript)
? What's the name of your extension? TODO Radar
? What's the identifier of your extension? todo-radar
? What's the description of your extension? Repère et liste les TODO, FIXME et HACK du projet
? Initialize a git repository? Yes
? Which bundler to use? esbuild
? Which package manager to use? npm
? Do you want to open the new folder with Visual Studio Code? Open with `code`

On choisit esbuild dès maintenant. Une extension non bundlée embarque tout son node_modules, se charge lentement et pèse lourd. Le chapitre 7 détaille la configuration.

Ce qui a été généré

todo-radar/
├── .vscode/
│   ├── launch.json          ← configuration F5 : lance l'Extension Development Host
│   ├── tasks.json           ← tâche de build en mode watch
│   └── extensions.json      ← extensions recommandées pour développer
├── src/
│   ├── extension.ts         ← point d'entrée : activate() et deactivate()
│   └── test/
│       └── extension.test.ts
├── esbuild.js               ← script de bundling
├── .vscode-test.mjs         ← configuration des tests
├── .vscodeignore            ← fichiers exclus du paquet publié
├── package.json             ← le manifeste de l'extension
├── tsconfig.json
├── CHANGELOG.md
└── README.md                ← devient la page du Marketplace

Deux fichiers comptent vraiment : package.json, qui déclare, et src/extension.ts, qui implémente.

Le manifeste package.json

C'est un package.json npm classique, enrichi de champs propres à VS Code.

package.json
{
  "name": "todo-radar",
  "displayName": "TODO Radar",
  "description": "Repère et liste les TODO, FIXME et HACK du projet",
  "version": "0.0.1",
  "engines": {
    "vscode": "^1.100.0"
  },
  "categories": ["Other"],
  "activationEvents": [],
  "main": "./dist/extension.js",
  "contributes": {
    "commands": [
      {
        "command": "todo-radar.helloWorld",
        "title": "Hello World"
      }
    ]
  },
  "scripts": {
    "vscode:prepublish": "npm run package",
    "compile": "npm run check-types && node esbuild.js",
    "watch": "node esbuild.js --watch",
    "package": "npm run check-types && node esbuild.js --production",
    "check-types": "tsc --noEmit",
    "test": "vscode-test"
  }
}

Les champs à connaître :

ChampRôle
nameIdentifiant technique, en minuscules. Avec publisher, il forme l'ID unique publisher.name
displayNameNom affiché dans le Marketplace et le panneau Extensions
engines.vscodeVersion minimale de VS Code. L'extension ne s'installe pas sur une version plus ancienne
mainFichier JavaScript chargé à l'activation (le bundle, pas le TypeScript)
activationEventsQuand charger l'extension. Vide ici : les commandes déclarées suffisent depuis VS Code 1.74
contributesTout ce que l'extension ajoute à l'interface, de façon déclarative

engines.vscode mérite réflexion. Le générateur y met votre version actuelle. Plus elle est récente, plus vous avez d'API, et moins vous touchez d'utilisateurs bloqués sur une version d'entreprise. Une version d'un an en arrière est un bon compromis.

La version de @types/vscode, dans les devDependencies, doit correspondre à engines.vscode. Si vous utilisez une API typée en 1.105 avec un moteur à 1.100, l'extension plantera chez ceux qui ont la 1.100.

Le point d'entrée extension.ts

src/extension.ts
import * as vscode from 'vscode'
 
export function activate(context: vscode.ExtensionContext) {
  console.log('TODO Radar est actif')
 
  const disposable = vscode.commands.registerCommand('todo-radar.helloWorld', () => {
    vscode.window.showInformationMessage('Hello World from TODO Radar!')
  })
 
  context.subscriptions.push(disposable)
}
 
export function deactivate() {}

Trois idées dans ces quelques lignes.

activate est appelée une seule fois, au premier événement d'activation. On y enregistre tout ce dont l'extension a besoin.

Le lien entre manifeste et code passe par l'identifiant de commande. todo-radar.helloWorld est déclaré dans contributes.commands (pour que la commande apparaisse dans la palette) et implémenté par registerCommand. Si les deux chaînes diffèrent, la commande s'affiche mais renvoie « command not found ».

Tout ce qu'on enregistre renvoie un Disposable. On le pousse dans context.subscriptions ; VS Code libère tout à la désactivation. Oublier cette ligne, c'est laisser des écouteurs actifs après un rechargement.

Lancer avec F5

Appuyez sur F5. VS Code compile le projet en mode watch puis ouvre une seconde fenêtre, titrée [Extension Development Host]. Votre extension y est chargée depuis les sources.

Dans cette fenêtre, ouvrez la palette (Ctrl+Shift+P) et tapez « Hello World ». La notification apparaît. Dans la fenêtre d'origine, la console de débogage affiche TODO Radar est actif.

Le cycle de développement devient :

  1. modifier src/extension.ts et enregistrer (la tâche watch recompile) ;
  2. dans la fenêtre de développement, Ctrl+R ou Developer: Reload Window ;
  3. tester.

Les points d'arrêt posés dans le TypeScript fonctionnent : les source maps relient le bundle au code source.

Remplacer Hello World par une vraie commande

Première brique de TODO Radar : compter les marqueurs dans le fichier ouvert. On isole la logique de détection dans un module sans dépendance à vscode, ce qui la rendra testable en pur Node.js au chapitre 7.

src/scanner.ts
export interface TodoMatch {
  tag: string
  text: string
  line: number
  column: number
}
 
export const DEFAULT_TAGS = ['TODO', 'FIXME', 'HACK']
 
export function scanText(source: string, tags: string[] = DEFAULT_TAGS): TodoMatch[] {
  const pattern = new RegExp(`\\b(${tags.join('|')})\\b[:\\s]*(.*)`)
  const matches: TodoMatch[] = []
 
  source.split(/\r?\n/).forEach((content, line) => {
    const m = pattern.exec(content)
    if (m) {
      matches.push({ tag: m[1], text: m[2].trim(), line, column: m.index })
    }
  })
 
  return matches
}

Si l'expression régulière vous semble opaque, l'article sur les expressions régulières décortique les groupes de capture et \b.

On branche ce scanner sur une commande :

src/extension.ts
import * as vscode from 'vscode'
import { scanText } from './scanner'
 
export function activate(context: vscode.ExtensionContext) {
  context.subscriptions.push(
    vscode.commands.registerCommand('todo-radar.countInFile', () => {
      const editor = vscode.window.activeTextEditor
      if (!editor) {
        vscode.window.showWarningMessage('Aucun fichier ouvert.')
        return
      }
 
      const matches = scanText(editor.document.getText())
      vscode.window.showInformationMessage(
        `${matches.length} marqueur(s) dans ${vscode.workspace.asRelativePath(editor.document.uri)}`
      )
    })
  )
}
 
export function deactivate() {}

Et dans le manifeste, on remplace la commande générée :

package.json
"contributes": {
  "commands": [
    {
      "command": "todo-radar.countInFile",
      "title": "Compter les TODO du fichier",
      "category": "TODO Radar"
    }
  ]
}

category préfixe la commande dans la palette : elle s'affiche comme TODO Radar: Compter les TODO du fichier, ce qui la rend facile à retrouver.

L'objet vscode en un coup d'œil

L'API est grande, mais elle s'organise en quelques espaces de noms :

EspaceContenu
vscode.commandsEnregistrer et exécuter des commandes
vscode.windowÉditeurs ouverts, notifications, saisies, barre d'état, vues, webviews
vscode.workspaceFichiers du projet, configuration, événements de modification, système de fichiers
vscode.languagesDiagnostics, complétion, survol, actions de code, tout ce qui touche à un langage
vscode.envPresse-papiers, langue, ouverture d'URL externes
vscode.extensionsAccès aux autres extensions installées

Le typage de @types/vscode est la meilleure documentation : survolez une fonction, la description et les exemples sont dans les commentaires. Si les types vous freinent encore, le guide TypeScript pour développeurs JavaScript couvre ce qu'il faut pour suivre ce cours.


L'extension démarre, une commande fonctionne. Le chapitre suivant ajoute ce qui fait une extension utilisable : réglages, raccourcis, menus contextuels et activation au bon moment.

Précédent
Utiliser et gérer ses extensions
Suivant
Commandes, réglages et activation

Développeur fullstack passionné. J'apprends en construisant et je documente tout — front, back, outils. Le code s'apprend mieux en public.

Naviguer

IndexTous les articlesFormationsProfilOutilsBibliothech

Ailleurs

GitHub RSS

Newsletter

Les articles, libs et découvertes. Une fois par semaine, pas plus.

© 2026 William LoreeConçu & codé à la main