Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Code Block
import * as vscode from 'vscode';
import { DelveDebugAdapterDescriptorFactory } from './delveDebugAdapterFactory';

export function activate(context: vscode.ExtensionContext) {
    console.log('Hyperledger Chaincode Debugger is active.');

    // Register the debug adapter factory
    context.subscriptions.push(
        vscode.debug.registerDebugAdapterDescriptorFactory('delve', new DelveDebugAdapterDescriptorFactory())
    );

    // Listen for debugging session events
    vscode.debug.onDidStartDebugSession((session) => {
        console.log(`Debugging started: ${session.name}`);
        vscode.window.showInformationMessage(`Debugging started: ${session.name}`);
    });

    vscode.debug.onDidTerminateDebugSession((session) => {
        console.log(`Debugging terminated: ${session.name}`);
        vscode.window.showInformationMessage(`Debugging terminated: ${session.name}`);
    });
}

export function deactivate() {
    console.log('Hyperledger Chaincode Debugger is deactivated.');
}

Code Block
import * as vscode from 'vscode';
import { spawn, ChildProcess } from 'child_process';
import * as path from 'path';
import { DelveDebugAdapter } from './delveDebugAdapter';

export class DelveDebugAdapterDescriptorFactory implements vscode.DebugAdapterDescriptorFactory {
    private delveProcess: ChildProcess | undefined;

    createDebugAdapterDescriptor(
        session: vscode.DebugSession
    ): vscode.ProviderResult<vscode.DebugAdapterDescriptor> {
        const config = session.configuration;
        const program = config.program;
        const port = config.port || 2345;

        if (!program) {
            vscode.window.showErrorMessage('No program specified to debug.');
            return;
        }

        // Start Delve as a headless server
        this.delveProcess = spawn('dlv', [
            'debug',
            '--headless',
            `--listen=127.0.0.1:${port}`,
            '--log',
            '--api-version=2',
            program
        ], {
            cwd: path.dirname(program),
            env: process.env
        });

        this.delveProcess.stdout.on('data', (data) => {
            console.log(`Delve: ${data}`);
        });

        this.delveProcess.stderr.on('data', (data) => {
            console.error(`Delve Error: ${data}`);
        });

        this.delveProcess.on('exit', (code) => {
            console.log(`Delve exited with code ${code}`);
        });

        // Return a custom debug adapter to handle requests
        return new DelveDebugAdapter(port, '127.0.0.1');
    }

    dispose() {
        if (this.delveProcess) {
            this.delveProcess.kill();
            this.delveProcess = undefined;
        }
    }
}
Code Block
import { DebugSession, InitializedEvent, StoppedEvent, TerminatedEvent } from '@vscode/debugadapter';
import { DebugProtocol } from '@vscode/debugprotocol';
import { Socket } from 'net';

export class DelveDebugAdapter extends DebugSession {
    private socket: Socket;

    constructor(port: number, host: string) {
        super();

        // Connect to the Delve server
        this.socket = new Socket();
        this.socket.connect(port, host, () => {
            console.log('Connected to Delve server');
        });

        this.socket.on('data', (data) => {
            console.log(`Received data from Delve: ${data}`);
        });

        this.socket.on('error', (err) => {
            console.error(`Socket error: ${err.message}`);
        });

        this.socket.on('close', () => {
            console.log('Connection to Delve server closed');
        });
    }

    protected async dispatchRequest(request: DebugProtocol.Request): Promise<void> {
        console.log(`Received request: ${request.command}`);

        switch (request.command) {
            case 'initialize':
                console.log('Debugging session initialized');
                break;

            case 'next':
                console.log('User clicked Step Over');
                break;

            case 'stepIn':
                console.log('User clicked Step In');
                break;

            case 'stepOut':
                console.log('User clicked Step Out');
                break;

            case 'continue':
                console.log('User clicked Continue');
                break;

            case 'pause':
                console.log('User clicked Pause');
                break;

            default:
                console.log(`Unhandled command: ${request.command}`);
        }

        // Forward the request to Delve
        this.socket.write(JSON.stringify(request));
        await super.dispatchRequest(request);
    }

    dispose() {
        this.socket.destroy();
    }
}
Code Block
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Debug Hyperledger Chaincode (Delve Server)",
      "type": "delve",
      "request": "launch",
      "program": "${workspaceFolder}/path/to/chaincode",
      "port": 2345
    }
  ]
}