Créer une extension VS Code en TypeScript pour gagner du temps

Visual Studio Code domine le paysage des éditeurs de code grâce à la richesse de son écosystème d'extensions. Pourtant, derrière cette modularité se cache une frustration quotidienne : chaque équipe finit par reproduire les mêmes ajustements manuels, qu'il s'agisse d'injecter un en-tête de licence, de reformater un fichier YAML ou de basculer entre projets selon une convention maison. Concevoir un plugin sur mesure convertit ces frictions en gestes automatisés, déclenchables depuis la palette de commandes ou un raccourci clavier.

TypeScript s'impose comme le langage naturel pour cette tâche. L'API de VS Code est entièrement typée, l'autocomplétion guide l'écriture et le compilateur attrape les erreurs avant l'exécution. Que vous visiez un outil interne ou une contribution publique sur le Marketplace, le duo TypeScript + VS Code fournit un socle productif.

Préparer son terrain de jeu

Avant la première ligne de code, rassemblez les briques élémentaires : Node.js en version LTS, un gestionnaire de paquets comme npm ou pnpm, et l'extension « ESLint » dans votre éditeur. Activez aussi le mode « Workspace Trust » si vos manipulations toucheront à des dépôts sensibles, et vérifiez que la commande code est disponible dans votre terminal pour lancer rapidement l'instance de test.

Comparons rapidement leurs caractéristiques respectives :

Approche Complexité de mise en place Portée Maintenance requise
Extrait de code (snippet) Très faible Fichier courant Quasi nulle
Tâche VS Code (tasks.json) Faible Projet Faible
Macro multi-commandes Moyenne Session courante Limitée
Extension TypeScript Élevée Workspace complet Active

L'extension écrite en TypeScript représente l'option la plus lourde, mais aussi la plus puissante : elle survit aux redémarrages, expose son interface dans la palette de commandes et peut embarquer sa propre vue latérale.

Scaffolding avec Yeoman

Le générateur yo code automatise la création du squelette. Installez-le via npm install -g yo generator-code, puis exécutez yo code dans un dossier vide. L'assistant pose les questions clés : type d'extension, identifiant unique, gestionnaire de paquets préféré. En sortie, vous obtenez un package.json correctement rempli, un tsconfig.json strict et un script de watch prêt à l'emploi.

Pour structurer vos commandes selon une logique événementielle claire, l'inspiration vient du pattern CQRS avec événements : chaque action utilisateur publie un événement qu'un gestionnaire dédié traite, ce qui découple l'interface de la logique métier.

Anatomie d'un projet d'extension

Quatre fichiers forment l'ossature d'une extension. Le package.json déclare les contributions (commandes, menus, thèmes, points d'activation). Le dossier src héberge le code TypeScript, compilé vers out/ à chaque build. Le fichier extension.ts sert de point d'entrée ; sa fonction activate reçoit un contexte et enregistre les commandes, tandis que deactivate libère proprement les ressources, par exemple en fermant des clients de langage ou en vidant des caches.

Une convention efficace consiste à regrouper les commandes par thème dans des fichiers dédiés (commands/format.ts, commands/scaffold.ts), importés depuis un index central. Cette découpe facilite les tests unitaires et limite les fusions douloureuses lorsqu'une nouvelle personne rejoint le projet.

Implémenter des commandes contextuelles

Chaque commande reçoit un objet TextEditor qui expose la sélection courante, le document et la position du curseur. Envelopper une sélection dans un console.log ne prend que quelques lignes : récupérez le texte, créez un SnippetString et remplacez la sélection initiale.

Pour des interactions plus riches, exploitez showQuickPick ou showInputBox, qui acceptent valeurs par défaut et validateurs. Pensez à déclarer vos raccourcis clavier dans la section contributes.keybindings du manifest. Quand la commande doit manipuler plusieurs fichiers ou consulter des préférences persistantes, certains auteurs comparent les solutions de base cloud pour choisir où stocker leurs paramètres partagés.

Tester, déboguer et itérer

Le générateur installe un harnais de test basé sur Mocha. Lancez la suite via la tâche « Extension Tests » du panneau de débogage ; elle s'exécute dans une instance isolée de VS Code, ce qui évite toute interférence avec votre installation principale.

Pour le développement courant, le mode « Run Extension » démarre une fenêtre secondaire attachée à votre code source. Placez des points d'arrêt dans extension.ts, manipulez l'interface et observez le flux d'exécution en direct. Créez un fichier *.test.ts à côté de chaque module : vous gagnez du temps et maintenez une couverture élevée même pour un utilitaire personnel.

Publication et maintenance sur le Marketplace

L'outil vsce enchaîne empaquetage et publication. Générez un jeton d'accès personnel sur Azure DevOps, connectez-vous via vsce login <publisher>, puis exécutez vsce publish. Le numéro de version est lu depuis le package.json, et un message de release peut être attaché via --message.

Microsoft héberge le binaire et les mises à jour, mais vous pouvez compléter la diffusion en documentant votre projet sur votre propre espace cloud : page dédiée, captures d'écran, journal des versions. Après publication, surveillez les signalements d'incidents et alignez vos montées de version sur les canaux stable et insiders de l'éditeur.

Bonnes pratiques et prochaines étapes

Quelques principes accélèrent la maturité d'une extension :

Au-delà de ces règles, intégrez votre plugin dans une boucle d'amélioration continue : recueillez les retours des utilisateurs, mesurez les actions les plus invoquées et supprimez les commandes inutilisées. Une extension maintenue reste pertinente pendant des années.

Attaquez dès aujourd'hui un petit cas d'usage qui vous frustre au quotidien, comme renommer en lot des composants React ou générer un squelette de test unitaire. Votre premier plugin sera modeste, mais il posera les bases d'une boîte à outils taillée sur mesure, et chaque ajout ultérieur deviendra un investissement rentable pour l'ensemble de votre équipe.