Extension Architecture

Detailed description of the internal architecture of a WvdS VSCode Extension.

Lifecycle

┌─────────────────────────────────────────────────────────────┐
│                    EXTENSION LIFECYCLE                       │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  1. VS Code Start                                            │
│     ↓                                                        │
│  2. Activation Event triggers                                │
│     (onCommand, onLanguage, onStartupFinished, ...)          │
│     ↓                                                        │
│  3. extension_main.js is loaded                              │
│     ↓                                                        │
│  4. Activate() is called                                     │
│     → Initialize services                                    │
│     → Register commands                                      │
│     → Set up event handlers                                  │
│     ↓                                                        │
│  5. Extension is active                                      │
│     → User interaction                                       │
│     → Command execution                                      │
│     ↓                                                        │
│  6. VS Code Shutdown / Extension deactivated                 │
│     ↓                                                        │
│  7. Deactivate() is called                                   │
│     → Cleanup                                                │
│     → Release resources                                      │
│                                                              │
└─────────────────────────────────────────────────────────────┘

Entry Point

Every extension has exactly one entry point: extension_main.pas

unit extension_main;
 
{$mode objfpc}{$H+}
 
interface
 
uses
  JS, VSCode.API, VSCode.ExtensionExports;
 
procedure Activate(AContext: TExtensionContext);
procedure Deactivate;
 
implementation
 
procedure Activate(AContext: TExtensionContext);
begin
  // Initialization here
end;
 
procedure Deactivate;
begin
  // Cleanup here
end;
 
initialization
  ExportActivateDeactivate(@Activate, @Deactivate);
 
end.

Activation Events

Event Description Example
onStartupFinished After VS Code start Core Extension
onCommand:* On command invocation wvds.build.run
onLanguage:* On file open pascal, pxaml
onView:* On view open wvds.toolbox
workspaceContains:** When file exists *.lpr, *.pas
onCustomEditor:* On custom editor wvds.designer

Command Registration

procedure RegisterCommands(AContext: TExtensionContext);
begin
  // Simple command
  RegisterCommand('wvds.feature.action', @HandleAction);
 
  // Command with arguments
  RegisterCommand('wvds.feature.open', @HandleOpen);
 
  // Asynchronous command
  RegisterAsyncCommand('wvds.feature.process', @HandleProcessAsync);
end;
 
procedure HandleAction(Args: TJSValueDynArray);
begin
  ShowInfoMessage('Action executed');
end;
 
function HandleProcessAsync(Args: TJSValueDynArray): TJSPromise;
begin
  Result := TJSPromise.New(
    procedure(Resolve, Reject: TJSPromiseResolver)
    begin
      // Async work...
      Resolve(nil);
    end
  );
end;

Service Pattern

// Feature.Service.pas
unit Feature.Service;
 
interface
 
type
  TWvdSFeatureService = class
  private
    FInitialized: Boolean;
  public
    procedure Initialize;
    procedure Shutdown;
    function DoWork(const AInput: string): string;
  end;
 
var
  FeatureService: TWvdSFeatureService;
 
implementation
 
procedure TWvdSFeatureService.Initialize;
begin
  if FInitialized then Exit;
  // Initialize service
  FInitialized := True;
end;
 
procedure TWvdSFeatureService.Shutdown;
begin
  if not FInitialized then Exit;
  // Clean up
  FInitialized := False;
end;
 
initialization
  FeatureService := TWvdSFeatureService.Create;
 
finalization
  FeatureService.Free;
 
end.

Disposables

VS Code uses Disposables for resource management:

procedure Activate(AContext: TExtensionContext);
var
  Disposable: TDisposable;
begin
  // Register command and get Disposable
  Disposable := RegisterCommand('wvds.test', @Handler);
 
  // Add to context for automatic cleanup
  AContext.Subscriptions.Push(Disposable);
end;

WebView Integration

procedure ShowWebViewPanel;
var
  Panel: TWebviewPanel;
begin
  Panel := CreateWebviewPanel(
    'wvds.feature.panel',     // viewType
    'Feature Panel',           // title
    ViewColumn.One,           // showOptions
    WebviewOptions            // options
  );
 
  // Set HTML
  Panel.Webview.Html := GetPanelHtml;
 
  // Set up messaging
  Panel.Webview.OnDidReceiveMessage(@HandleWebviewMessage);
 
  // Send messages
  Panel.Webview.PostMessage(TJSObject.New);
end;

Event Handling

procedure SetupEventHandlers;
begin
  // Configuration change
  OnDidChangeConfiguration(@HandleConfigChange);
 
  // Document events
  OnDidOpenTextDocument(@HandleDocumentOpen);
  OnDidSaveTextDocument(@HandleDocumentSave);
  OnDidCloseTextDocument(@HandleDocumentClose);
 
  // Workspace events
  OnDidChangeWorkspaceFolders(@HandleWorkspaceChange);
end;

See Also

Zuletzt geändert: on 2026/01/29 at 10:26 PM