ist jetzt verfügbar! Lesen Sie über die neuen Funktionen und Fehlerbehebungen vom November.

Debugger-Erweiterung

Die Debugging-Architektur von Visual Studio Code ermöglicht es Erweiterungsautoren, vorhandene Debugger einfach in VS Code zu integrieren, während sie eine gemeinsame Benutzeroberfläche für alle haben.

VS Code wird mit einer integrierten Debugger-Erweiterung ausgeliefert, der Node.js Debugger-Erweiterung, die eine hervorragende Demonstration der vielen von VS Code unterstützten Debugger-Funktionen ist.

VS Code Debug Features

Diese Bildschirmaufnahme zeigt die folgenden Debugging-Funktionen

  1. Verwaltung von Debug-Konfigurationen.
  2. Debug-Aktionen zum Starten/Stoppen und schrittweisen Ausführen.
  3. Quell-, Funktions-, bedingte-, Inline-Breakpoints und Log-Punkte.
  4. Stack-Traces, einschließlich Unterstützung für mehrere Threads und Prozesse.
  5. Navigieren durch komplexe Datenstrukturen in Ansichten und Hover-Informationen.
  6. Variablenwerte, die in Hover-Informationen oder direkt im Quellcode angezeigt werden.
  7. Verwaltung von Watch-Ausdrücken.
  8. Debug-Konsole für interaktive Auswertung mit Autovervollständigung.

Diese Dokumentation hilft Ihnen bei der Erstellung einer Debugger-Erweiterung, mit der jeder Debugger mit VS Code funktionieren kann.

Debugging-Architektur von VS Code

VS Code implementiert eine generische (sprachunabhängige) Debugger-Benutzeroberfläche, die auf einem abstrakten Protokoll basiert, das wir eingeführt haben, um mit Debugger-Backends zu kommunizieren. Da Debugger dieses Protokoll typischerweise nicht implementieren, ist ein Vermittler erforderlich, um den Debugger an das Protokoll "anzupassen". Dieser Vermittler ist typischerweise ein eigenständiger Prozess, der mit dem Debugger kommuniziert.

VS Code Debug Architecture

Diesen Vermittler nennen wir Debug Adapter (oder kurz DA) und das abstrakte Protokoll, das zwischen dem DA und VS Code verwendet wird, ist das Debug Adapter Protocol (kurz DAP). Da das Debug Adapter Protocol unabhängig von VS Code ist, hat es eine eigene Website, auf der Sie eine Einführung und Übersicht, die detaillierte Spezifikation und einige Listen mit bekannten Implementierungen und unterstützenden Tools finden. Die Geschichte und Motivation hinter DAP wird in diesem Blog-Beitrag erklärt.

Da Debug-Adapter unabhängig von VS Code sind und in anderen Entwicklungstools verwendet werden können, passen sie nicht zur Erweiterbarkeitsarchitektur von VS Code, die auf Erweiterungen und Beitragspunkten basiert.

Aus diesem Grund bietet VS Code einen Beitragspunkt, debuggers, an, an dem ein Debug-Adapter unter einem bestimmten Debug-Typ (z. B. node für den Node.js-Debugger) beigetragen werden kann. VS Code startet den registrierten DA, wann immer der Benutzer eine Debug-Sitzung dieses Typs startet.

In seiner minimalsten Form ist eine Debugger-Erweiterung also lediglich ein deklarativer Beitrag einer Debug-Adapter-Implementierung, und die Erweiterung ist im Grunde ein Verpackungscontainer für den Debug-Adapter ohne zusätzlichen Code.

VS Code Debug Architecture 2

Eine realistischere Debugger-Erweiterung trägt viele oder alle der folgenden deklarativen Elemente zu VS Code bei:

  • Liste der vom Debugger unterstützten Sprachen. VS Code aktiviert die Benutzeroberfläche zum Setzen von Breakpoints für diese Sprachen.
  • JSON-Schema für die vom Debugger eingeführten Attribute der Debug-Konfiguration. VS Code verwendet dieses Schema, um die Konfiguration im launch.json-Editor zu überprüfen und bietet IntelliSense. Bitte beachten Sie, dass die JSON-Schema-Konstrukte $ref und definition nicht unterstützt werden.
  • Standard-Debug-Konfigurationen für den initialen launch.json, der von VS Code erstellt wird.
  • Debug-Konfigurations-Snippets, die ein Benutzer zur launch.json-Datei hinzufügen kann.
  • Deklaration von Variablen, die in Debug-Konfigurationen verwendet werden können.

Weitere Informationen finden Sie in den Referenzen contributes.breakpoints und contributes.debuggers.

Zusätzlich zu den rein deklarativen Beiträgen von oben ermöglicht die Debug Extension API diese codebasierten Funktionalitäten:

  • Dynamisch generierte Standard-Debug-Konfigurationen für den initialen launch.json, der von VS Code erstellt wird.
  • Dynamische Bestimmung des zu verwendenden Debug-Adapters.
  • Überprüfung oder Änderung von Debug-Konfigurationen, bevor sie an den Debug-Adapter übergeben werden.
  • Kommunikation mit dem Debug-Adapter.
  • Senden von Nachrichten an die Debug-Konsole.

Im Rest dieses Dokuments zeigen wir, wie eine Debugger-Erweiterung entwickelt wird.

Die Mock Debug Extension

Da die Erstellung eines Debug-Adapters von Grund auf für dieses Tutorial etwas aufwendig ist, beginnen wir mit einem einfachen DA, den wir als lehrreiches "Debug Adapter Starter Kit" erstellt haben. Er heißt Mock Debug, da er nicht mit einem echten Debugger spricht, sondern einen simuliert. Mock Debug simuliert einen Debugger und unterstützt Schrittausführung, Fortsetzen, Breakpoints, Ausnahmen und den Zugriff auf Variablen, ist aber nicht mit einem echten Debugger verbunden.

Bevor wir uns mit dem Entwicklungs-Setup für mock-debug befassen, installieren wir zunächst eine vorkompilierte Version aus dem VS Code Marketplace und spielen damit herum.

  • Wechseln Sie zur Erweiterungsansicht und geben Sie "mock" ein, um nach der Mock Debug-Erweiterung zu suchen.
  • "Installieren" und "Neu laden" Sie die Erweiterung.

Um Mock Debug auszuprobieren

  • Erstellen Sie einen neuen leeren Ordner mock test und öffnen Sie ihn in VS Code.
  • Erstellen Sie eine Datei readme.md und geben Sie mehrere Zeilen beliebigen Text ein.
  • Wechseln Sie zur Ansicht "Ausführen und Debuggen" (⇧⌘D (Windows, Linux Ctrl+Shift+D)) und wählen Sie den Link launch.json-Datei erstellen.
  • VS Code lässt Sie einen "Debugger" auswählen, um eine Standard-Launch-Konfiguration zu erstellen. Wählen Sie "Mock Debug".
  • Drücken Sie die grüne Schaltfläche Start und dann Enter, um die vorgeschlagene Datei readme.md zu bestätigen.

Eine Debug-Sitzung wird gestartet, und Sie können durch die readme-Datei "schreiten", Breakpoints setzen und treffen, und auf Ausnahmen stoßen (wenn das Wort exception in einer Zeile vorkommt).

Mock Debugger running

Bevor Sie Mock Debug als Ausgangspunkt für Ihre eigene Entwicklung verwenden, empfehlen wir, die vorkompilierte Version zuerst zu deinstallieren.

  • Wechseln Sie zur Erweiterungsansicht und klicken Sie auf das Zahnradsymbol der Mock Debug-Erweiterung.
  • Führen Sie die Aktion "Deinstallieren" und dann "Fenster neu laden" aus.

Entwicklungs-Setup für Mock Debug

Nun holen wir uns den Quellcode von Mock Debug und beginnen mit der Entwicklung darin in VS Code.

git clone https://github.com/microsoft/vscode-mock-debug.git
cd vscode-mock-debug
yarn

Öffnen Sie den Projektordner vscode-mock-debug in VS Code.

Was ist im Paket enthalten?

  • package.json ist das Manifest für die mock-debug-Erweiterung.
    • Es listet die Beiträge der mock-debug-Erweiterung auf.
    • Die Skripte compile und watch werden verwendet, um den TypeScript-Quellcode in den Ordner out zu transpilieren und auf nachfolgende Quellcodeänderungen zu achten.
    • Die Abhängigkeiten vscode-debugprotocol, vscode-debugadapter und vscode-debugadapter-testsupport sind NPM-Module, die die Entwicklung von Node-basierten Debug-Adaptern vereinfachen.
  • src/mockRuntime.ts ist eine Mock-Laufzeitumgebung mit einer einfachen Debug-API.
  • Der Code, der die Laufzeitumgebung an das Debug Adapter Protocol anpasst, befindet sich in src/mockDebug.ts. Hier finden Sie die Handler für die verschiedenen Anfragen des DAP.
  • Da die Implementierung der Debugger-Erweiterung im Debug-Adapter liegt, ist kein Erweiterungscode erforderlich (d. h. Code, der im Erweiterungs-Host-Prozess ausgeführt wird). Mock Debug verfügt jedoch über ein kleines src/extension.ts, da es veranschaulicht, was im Erweiterungscode einer Debugger-Erweiterung getan werden kann.

Bauen und starten Sie nun die Mock Debug-Erweiterung, indem Sie die Startkonfiguration Extension auswählen und F5 drücken. Anfangs wird dies eine vollständige Transpilierung der TypeScript-Quellen in den Ordner out durchführen. Nach dem vollständigen Build wird eine Watcher-Aufgabe gestartet, die alle von Ihnen vorgenommenen Änderungen transpilieren.

Nach der Transpilierung des Quellcodes erscheint ein neues VS Code-Fenster mit der Bezeichnung "[Extension Development Host]", in dem die Mock Debug-Erweiterung nun im Debug-Modus ausgeführt wird. Öffnen Sie von diesem Fenster aus Ihr mock test-Projekt mit der readme.md-Datei, starten Sie eine Debug-Sitzung mit 'F5' und durchlaufen Sie sie dann schrittweise.

Debugging Extension and Server

Da Sie die Erweiterung im Debug-Modus ausführen, könnten Sie nun Breakpoints in src/extension.ts setzen und treffen, aber wie bereits erwähnt, wird dort nicht viel interessanter Code ausgeführt. Der interessante Code läuft im Debug-Adapter, der ein separater Prozess ist.

Um den Debug-Adapter selbst zu debuggen, müssen wir ihn im Debug-Modus ausführen. Dies ist am einfachsten zu erreichen, indem der Debug-Adapter im Servermodus ausgeführt und VS Code so konfiguriert wird, dass er sich damit verbindet. Wählen Sie in Ihrem VS Code vscode-mock-debug-Projekt die Startkonfiguration Server aus dem Dropdown-Menü aus und drücken Sie die grüne Startschaltfläche.

Da wir bereits eine aktive Debug-Sitzung für die Erweiterung hatten, wechselt die VS Code-Debugger-Benutzeroberfläche nun in den Multi-Session-Modus, was durch die Namen der beiden Debug-Sitzungen Extension und Server im CALL STACK-Fenster angezeigt wird.

Debugging Extension and Server

Nun sind wir in der Lage, sowohl die Erweiterung als auch den DA gleichzeitig zu debuggen. Ein schnellerer Weg dorthin ist die Verwendung der Startkonfiguration Extension + Server, die beide Sitzungen automatisch startet.

Ein alternativer, noch einfacherer Ansatz zum Debuggen der Erweiterung und des DA finden Sie weiter unten.

Setzen Sie einen Breakpoint am Anfang der Methode launchRequest(...) in der Datei src/mockDebug.ts und konfigurieren Sie als letzten Schritt den Mock-Debugger so, dass er sich mit dem DA-Server verbindet, indem Sie Ihrer mock test-Launch-Konfiguration ein Attribut debugServer für Port 4711 hinzufügen.

{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "mock",
      "request": "launch",
      "name": "mock test",
      "program": "${workspaceFolder}/readme.md",
      "stopOnEntry": true,
      "debugServer": 4711
    }
  ]
}

Wenn Sie diese Debug-Konfiguration jetzt starten, startet VS Code den Mock Debug-Adapter nicht als separaten Prozess, sondern verbindet sich direkt mit dem lokalen Port 4711 des bereits laufenden Servers, und Sie sollten den Breakpoint in launchRequest treffen.

Mit dieser Einrichtung können Sie nun Mock Debug einfach bearbeiten, transpilieren und debuggen.

Aber jetzt beginnt die eigentliche Arbeit: Sie müssen die Mock-Implementierung des Debug-Adapters in src/mockDebug.ts und src/mockRuntime.ts durch Code ersetzen, der mit einem "echten" Debugger oder einer Laufzeitumgebung spricht. Dies beinhaltet das Verständnis und die Implementierung des Debug Adapter Protocols. Weitere Details dazu finden Sie hier.

Aufbau der package.json einer Debugger-Erweiterung

Zusätzlich zur Bereitstellung einer Debugger-spezifischen Implementierung des Debug-Adapters benötigt eine Debugger-Erweiterung eine package.json, die zu den verschiedenen Debug-bezogenen Beitragspunkten beiträgt.

Werfen wir also einen genaueren Blick auf die package.json von Mock Debug.

Wie jede VS Code-Erweiterung deklariert die package.json die grundlegenden Eigenschaften name, publisher und version der Erweiterung. Verwenden Sie das Feld categories, um die Erweiterung im VS Code Extension Marketplace leichter auffindbar zu machen.

{
  "name": "mock-debug",
  "displayName": "Mock Debug",
  "version": "0.24.0",
  "publisher": "...",
  "description": "Starter extension for developing debug adapters for VS Code.",
  "author": {
    "name": "...",
    "email": "..."
  },
  "engines": {
    "vscode": "^1.17.0",
    "node": "^7.9.0"
  },
  "icon": "images/mock-debug-icon.png",
  "categories": ["Debuggers"],

  "contributes": {
    "breakpoints": [{ "language": "markdown" }],
    "debuggers": [
      {
        "type": "mock",
        "label": "Mock Debug",

        "program": "./out/mockDebug.js",
        "runtime": "node",

        "configurationAttributes": {
          "launch": {
            "required": ["program"],
            "properties": {
              "program": {
                "type": "string",
                "description": "Absolute path to a text file.",
                "default": "${workspaceFolder}/${command:AskForProgramName}"
              },
              "stopOnEntry": {
                "type": "boolean",
                "description": "Automatically stop after launch.",
                "default": true
              }
            }
          }
        },

        "initialConfigurations": [
          {
            "type": "mock",
            "request": "launch",
            "name": "Ask for file name",
            "program": "${workspaceFolder}/${command:AskForProgramName}",
            "stopOnEntry": true
          }
        ],

        "configurationSnippets": [
          {
            "label": "Mock Debug: Launch",
            "description": "A new configuration for launching a mock debug program",
            "body": {
              "type": "mock",
              "request": "launch",
              "name": "${2:Launch Program}",
              "program": "^\"\\${workspaceFolder}/${1:Program}\""
            }
          }
        ],

        "variables": {
          "AskForProgramName": "extension.mock-debug.getProgramName"
        }
      }
    ]
  },

  "activationEvents": ["onDebug", "onCommand:extension.mock-debug.getProgramName"]
}

Betrachten wir nun den Abschnitt contributes, der die für Debug-Erweiterungen spezifischen Beiträge enthält.

Zuerst verwenden wir den Beitragspunkt breakpoints, um die Sprachen aufzulisten, für die das Setzen von Breakpoints aktiviert wird. Ohne dies wäre es nicht möglich, Breakpoints in Markdown-Dateien zu setzen.

Als Nächstes kommt der Abschnitt debuggers. Hier wird ein Debugger unter einem Debug-type mock eingeführt. Der Benutzer kann diesen Typ in Launch-Konfigurationen referenzieren. Das optionale Attribut label kann verwendet werden, um dem Debug-Typ einen schönen Namen zu geben, wenn er in der Benutzeroberfläche angezeigt wird.

Da die Debug-Erweiterung einen Debug-Adapter verwendet, wird ein relativer Pfad zu seinem Code als Attribut program angegeben. Um die Erweiterung in sich geschlossen zu machen, muss die Anwendung im Erweiterungsordner liegen. Konventionsgemäß behalten wir diese Anwendung in einem Ordner namens out oder bin, aber Sie können gerne einen anderen Namen verwenden.

Da VS Code auf verschiedenen Plattformen läuft, müssen wir sicherstellen, dass das DA-Programm die verschiedenen Plattformen ebenfalls unterstützt. Dafür haben wir folgende Optionen:

  1. Wenn das Programm plattformunabhängig implementiert ist, z. B. als Programm, das auf einer Laufzeitumgebung läuft, die auf allen unterstützten Plattformen verfügbar ist, können Sie diese Laufzeitumgebung über das Attribut runtime angeben. Derzeit unterstützt VS Code node und mono Laufzeitumgebungen. Unser Mock Debug-Adapter von oben verwendet diesen Ansatz.

  2. Wenn Ihre DA-Implementierung unterschiedliche ausführbare Dateien auf verschiedenen Plattformen benötigt, kann das Attribut program für spezifische Plattformen wie folgt qualifiziert werden:

    "debuggers": [{
        "type": "gdb",
        "windows": {
            "program": "./bin/gdbDebug.exe",
        },
        "osx": {
            "program": "./bin/gdbDebug.sh",
        },
        "linux": {
            "program": "./bin/gdbDebug.sh",
        }
    }]
    
  3. Eine Kombination beider Ansätze ist ebenfalls möglich. Das folgende Beispiel stammt vom Mono DA, der als Mono-Anwendung implementiert ist und eine Laufzeitumgebung unter macOS und Linux, aber nicht unter Windows benötigt.

    "debuggers": [{
        "type": "mono",
        "program": "./bin/monoDebug.exe",
        "osx": {
            "runtime": "mono"
        },
        "linux": {
            "runtime": "mono"
        }
    }]
    

configurationAttributes deklariert das Schema für die launch.json-Attribute, die für diesen Debugger verfügbar sind. Dieses Schema wird zur Validierung von launch.json und zur Unterstützung von IntelliSense und Hover-Hilfe beim Bearbeiten der Launch-Konfiguration verwendet.

Die initialConfigurations definieren den anfänglichen Inhalt der Standard-launch.json für diesen Debugger. Diese Informationen werden verwendet, wenn ein Projekt keine launch.json hat und ein Benutzer eine Debug-Sitzung startet oder den Link launch.json-Datei erstellen in der Ansicht "Ausführen und Debuggen" auswählt. In diesem Fall lässt VS Code den Benutzer eine Debug-Umgebung auswählen und erstellt dann die entsprechende launch.json.

Debugger Quickpick

Anstatt den anfänglichen Inhalt von launch.json statisch in der package.json zu definieren, ist es möglich, die anfänglichen Konfigurationen dynamisch zu berechnen, indem ein DebugConfigurationProvider implementiert wird (Details finden Sie im Abschnitt Verwendung eines DebugConfigurationProvider unten).

configurationSnippets definieren Launch-Konfigurations-Snippets, die in IntelliSense beim Bearbeiten von launch.json angezeigt werden. Als Konvention sollte das Attribut label eines Snippets mit dem Namen der Debug-Umgebung präfixiert werden, damit es in einer Liste vieler Snippet-Vorschläge klar identifiziert werden kann.

Der variables-Beitrag verknüpft "Variablen" mit "Befehlen". Diese Variablen können in der Launch-Konfiguration unter der Syntax ${command:xyz} verwendet werden, und die Variablen werden durch den vom gebundenen Befehl zurückgegebenen Wert ersetzt, wenn eine Debug-Sitzung gestartet wird.

Die Implementierung eines Befehls liegt in der Erweiterung und kann von einem einfachen Ausdruck ohne Benutzeroberfläche bis hin zu ausgefeilter Funktionalität reichen, die auf den in der Erweiterungs-API verfügbaren Benutzeroberflächenmerkmalen basiert. Mock Debug bindet eine Variable AskForProgramName an den Befehl extension.mock-debug.getProgramName. Die Implementierung dieses Befehls in src/extension.ts verwendet showInputBox, um dem Benutzer die Eingabe eines Programmnamens zu ermöglichen.

vscode.commands.registerCommand('extension.mock-debug.getProgramName', config => {
  return vscode.window.showInputBox({
    placeHolder: 'Please enter the name of a markdown file in the workspace folder',
    value: 'readme.md'
  });
});

Die Variable kann nun in jedem zeichenkettenbasierten Wert einer Launch-Konfiguration als ${command:AskForProgramName} verwendet werden.

Verwendung eines DebugConfigurationProvider

Wenn die statische Natur von Debug-Beiträgen in der package.json nicht ausreicht, kann ein DebugConfigurationProvider verwendet werden, um die folgenden Aspekte einer Debug-Erweiterung dynamisch zu steuern:

  • Die anfänglichen Debug-Konfigurationen für eine neu erstellte launch.json können dynamisch generiert werden, z. B. basierend auf kontextbezogenen Informationen, die im Arbeitsbereich verfügbar sind.
  • Eine Launch-Konfiguration kann aufgelöst (oder geändert) werden, bevor sie zum Starten einer neuen Debug-Sitzung verwendet wird. Dies ermöglicht das Auffüllen von Standardwerten basierend auf im Arbeitsbereich verfügbaren Informationen. Es gibt zwei Resolve-Methoden: resolveDebugConfiguration wird aufgerufen, bevor Variablen in der Launch-Konfiguration ersetzt werden, resolveDebugConfigurationWithSubstitutedVariables wird aufgerufen, nachdem alle Variablen ersetzt wurden. Die erstere muss verwendet werden, wenn die Validierungslogik zusätzliche Variablen in die Debug-Konfiguration einfügt. Die letztere muss verwendet werden, wenn die Validierungslogik Zugriff auf die endgültigen Werte aller Debug-Konfigurationsattribute benötigt.

Die MockConfigurationProvider in src/extension.ts implementiert resolveDebugConfiguration, um den Fall zu erkennen, dass eine Debug-Sitzung gestartet wird, wenn keine launch.json vorhanden ist, aber eine Markdown-Datei im aktiven Editor geöffnet ist. Dies ist ein typisches Szenario, bei dem der Benutzer eine Datei im Editor geöffnet hat und sie einfach debuggen möchte, ohne eine launch.json zu erstellen.

Ein Debug-Konfigurationsanbieter wird für einen bestimmten Debug-Typ über vscode.debug.registerDebugConfigurationProvider registriert, typischerweise in der activate-Funktion der Erweiterung. Um sicherzustellen, dass der DebugConfigurationProvider früh genug registriert wird, muss die Erweiterung aktiviert werden, sobald die Debug-Funktionalität genutzt wird. Dies kann einfach durch Konfigurieren der Erweiterungsaktivierung für das onDebug-Ereignis in der package.json erreicht werden.

"activationEvents": [
    "onDebug",
    // ...
],

Dieses Catch-all onDebug wird ausgelöst, sobald irgendeine Debug-Funktionalität genutzt wird. Dies funktioniert gut, solange die Erweiterung kostengünstige Startzeiten hat (d. h. nicht viel Zeit in ihrer Startsequenz verbringt). Wenn eine Debug-Erweiterung einen teuren Start hat (z. B. wegen des Startens eines Sprachservers), kann das onDebug-Aktivierungsereignis andere Debug-Erweiterungen negativ beeinflussen, da es ziemlich früh ausgelöst wird und keinen spezifischen Debug-Typ berücksichtigt.

Ein besserer Ansatz für teure Debug-Erweiterungen ist die Verwendung feingranularerer Aktivierungsereignisse:

  • onDebugInitialConfigurations wird kurz vor dem Aufruf der provideDebugConfigurations-Methode des DebugConfigurationProvider ausgelöst.
  • onDebugResolve:type wird kurz vor dem Aufruf der Methoden resolveDebugConfiguration oder resolveDebugConfigurationWithSubstitutedVariables des DebugConfigurationProvider für den angegebenen Typ ausgelöst.

Faustregel: Wenn die Aktivierung einer Debug-Erweiterung kostengünstig ist, verwenden Sie onDebug. Wenn sie teuer ist, verwenden Sie onDebugInitialConfigurations und/oder onDebugResolve, je nachdem, ob der DebugConfigurationProvider die entsprechenden Methoden provideDebugConfigurations und/oder resolveDebugConfiguration implementiert.

Veröffentlichung Ihrer Debugger-Erweiterung

Sobald Sie Ihre Debugger-Erweiterung erstellt haben, können Sie sie im Marketplace veröffentlichen.

  • Aktualisieren Sie die Attribute in der package.json, um die Benennung und den Zweck Ihrer Debugger-Erweiterung widerzuspiegeln.
  • Laden Sie sie wie in Publishing Extension beschrieben im Marketplace hoch.

Alternativer Ansatz zur Entwicklung einer Debugger-Erweiterung

Wie wir gesehen haben, beinhaltet die Entwicklung einer Debugger-Erweiterung typischerweise das Debuggen sowohl der Erweiterung als auch des Debug-Adapters in zwei parallelen Sitzungen. Wie oben erklärt, unterstützt VS Code dies gut, aber die Entwicklung könnte einfacher sein, wenn sowohl die Erweiterung als auch der Debug-Adapter ein einziges Programm wären, das in einer einzigen Debug-Sitzung debuggt werden könnte.

Dieser Ansatz ist tatsächlich problemlos machbar, solange Ihr Debug-Adapter in TypeScript/JavaScript implementiert ist. Die Grundidee ist, den Debug-Adapter direkt innerhalb der Erweiterung auszuführen und VS Code dazu zu bringen, sich damit zu verbinden, anstatt pro Sitzung einen neuen externen Debug-Adapter zu starten.

Dafür stellt VS Code eine Erweiterungs-API zur Verfügung, um zu steuern, wie ein Debug-Adapter erstellt und ausgeführt wird. Ein DebugAdapterDescriptorFactory hat eine Methode createDebugAdapterDescriptor, die von VS Code aufgerufen wird, wenn eine Debug-Sitzung gestartet wird und ein Debug-Adapter benötigt wird. Diese Methode muss ein Deskriptorobjekt (DebugAdapterDescriptor) zurückgeben, das beschreibt, wie der Debug-Adapter ausgeführt wird.

Derzeit unterstützt VS Code drei verschiedene Arten der Ausführung eines Debug-Adapters und bietet daher drei verschiedene Deskriptortypen:

  • DebugAdapterExecutable: Dieses Objekt beschreibt einen Debug-Adapter als externe ausführbare Datei mit einem Pfad und optionalen Argumenten und Laufzeitumgebung. Die ausführbare Datei muss das Debug Adapter Protocol implementieren und über stdin/stdout kommunizieren. Dies ist der Standardbetriebsmodus von VS Code, und VS Code verwendet diesen Deskriptor automatisch mit den entsprechenden Werten aus der package.json, wenn keine DebugAdapterDescriptorFactory explizit registriert ist.
  • DebugAdapterServer: Dieses Objekt beschreibt einen Debug-Adapter, der als Server ausgeführt wird und über einen bestimmten lokalen oder Remote-Port kommuniziert. Eine Debug-Adapter-Implementierung, die auf dem npm-Modul vscode-debugadapter basiert, unterstützt diesen Servermodus automatisch.
  • DebugAdapterInlineImplementation: Dieses Objekt beschreibt einen Debug-Adapter als JavaScript- oder TypeScript-Objekt, das die Schnittstelle vscode.DebugAdapter implementiert. Eine Debug-Adapter-Implementierung, die auf Version 1.38-pre.4 oder höher des npm-Moduls vscode-debugadapter basiert, implementiert die Schnittstelle automatisch.

Mock Debug zeigt Beispiele für die drei Arten von DebugAdapterDescriptorFactories und wie sie für den Debug-Typ 'mock' registriert werden. Der zu verwendende Ausführungsmodus kann durch Einstellen der globalen Variable runMode auf einen der möglichen Werte external, server oder inline ausgewählt werden.

Für die Entwicklung sind die Modi inline und server besonders nützlich, da sie das Debuggen von Erweiterung und Debug-Adapter innerhalb eines einzigen Prozesses ermöglichen.

© . This site is unofficial and not affiliated with Microsoft.