vscode-extension-debugger

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

VS Code Extension Debugger

VS Code扩展调试器

Overview

概述

This skill enables systematic debugging and bug fixing for VS Code extensions. It provides structured workflows for identifying root causes, analyzing error patterns, and implementing robust fixes while preventing regressions.
本Skill支持对VS Code扩展进行系统化调试与bug修复。它提供结构化流程用于定位根因、分析错误模式,并在防止回归的同时实现可靠修复。

When to Use This Skill

何时使用本Skill

  • Investigating runtime errors or crashes in extensions
  • Fixing memory leaks and dispose handler issues
  • Resolving WebView rendering or communication failures
  • Debugging extension activation or deactivation problems
  • Troubleshooting message passing between Extension and WebView
  • Fixing TypeScript compilation errors
  • Resolving race conditions and async operation issues
  • Debugging terminal-related functionality
  • 排查扩展中的运行时错误或崩溃
  • 修复内存泄漏与释放处理程序问题
  • 解决WebView渲染或通信失败问题
  • 调试扩展激活或停用故障
  • 排查扩展与WebView之间的消息传递问题
  • 修复TypeScript编译错误
  • 解决竞态条件与异步操作问题
  • 调试终端相关功能

Debugging Workflow

调试流程

Phase 1: Bug Triage and Reproduction

阶段1:Bug分类与复现

  1. Gather Information
    • Error messages and stack traces
    • Steps to reproduce
    • Environment details (VS Code version, OS, extension version)
    • Frequency (always, intermittent, specific conditions)
  2. Classify Bug Type
    CategorySymptomsPriority
    CrashExtension host crash, unhandled rejectionP0
    Memory LeakIncreasing memory usage over timeP0
    Data LossState not persisted, data corruptionP0
    FunctionalityFeature not working as expectedP1
    PerformanceSlow response, UI lagP1
    UI/UXVisual glitches, incorrect displayP2
  3. Create Minimal Reproduction
    • Isolate the failing scenario
    • Document exact steps
    • Identify triggering conditions
  1. 收集信息
    • 错误消息与堆栈跟踪
    • 复现步骤
    • 环境详情(VS Code版本、操作系统、扩展版本)
    • 出现频率(始终出现、间歇性出现、特定条件下出现)
  2. 分类Bug类型
    类别症状优先级
    崩溃扩展宿主崩溃、未处理的拒绝P0
    内存泄漏内存使用随时间增加P0
    数据丢失状态未持久化、数据损坏P0
    功能问题功能未按预期工作P1
    性能问题响应缓慢、UI卡顿P1
    UI/UX问题视觉故障、显示错误P2
  3. 创建最小复现案例
    • 隔离失败场景
    • 记录精确步骤
    • 确定触发条件

Phase 2: Root Cause Analysis

阶段2:根因分析

Error Analysis Strategy

错误分析策略

typescript
// Add strategic logging for investigation
console.log('[DEBUG] State before operation:', JSON.stringify(state));
try {
  await problematicOperation();
} catch (error) {
  console.error('[DEBUG] Error details:', {
    message: error.message,
    stack: error.stack,
    context: currentContext
  });
  throw error;
}
typescript
// Add strategic logging for investigation
console.log('[DEBUG] State before operation:', JSON.stringify(state));
try {
  await problematicOperation();
} catch (error) {
  console.error('[DEBUG] Error details:', {
    message: error.message,
    stack: error.stack,
    context: currentContext
  });
  throw error;
}

Common Root Cause Patterns

常见根因模式

1. Dispose Handler Issues
typescript
// Bug: Missing dispose registration
const listener = vscode.workspace.onDidChangeConfiguration(...);
// listener never disposed!

// Fix: Always register disposables
context.subscriptions.push(
  vscode.workspace.onDidChangeConfiguration(...)
);
2. Race Conditions
typescript
// Bug: Concurrent operations conflict
async function createTerminal() {
  if (isCreating) return; // Insufficient guard
  isCreating = true;
  // ... creation logic
}

// Fix: Use atomic operation pattern
private creationPromise: Promise<void> | null = null;

async function createTerminal(): Promise<void> {
  if (this.creationPromise) {
    return this.creationPromise;
  }
  this.creationPromise = this.doCreateTerminal();
  try {
    await this.creationPromise;
  } finally {
    this.creationPromise = null;
  }
}
3. WebView Message Timing
typescript
// Bug: Message sent before WebView ready
panel.webview.postMessage({ type: 'init', data });

// Fix: Wait for ready signal
panel.webview.onDidReceiveMessage(msg => {
  if (msg.type === 'ready') {
    panel.webview.postMessage({ type: 'init', data });
  }
});
4. Null/Undefined Reference
typescript
// Bug: Assuming object exists
const terminal = this.terminals.get(id);
terminal.write(data); // Crash if undefined!

// Fix: Defensive access with early return
const terminal = this.terminals.get(id);
if (!terminal) {
  console.warn(`Terminal ${id} not found`);
  return;
}
terminal.write(data);
5. Async/Await Errors
typescript
// Bug: Unhandled promise rejection
someAsyncFunction(); // No await, no catch!

// Fix: Proper error handling
try {
  await someAsyncFunction();
} catch (error) {
  vscode.window.showErrorMessage(`Operation failed: ${error.message}`);
}
1. 释放处理程序问题
typescript
// Bug: Missing dispose registration
const listener = vscode.workspace.onDidChangeConfiguration(...);
// listener never disposed!

// Fix: Always register disposables
context.subscriptions.push(
  vscode.workspace.onDidChangeConfiguration(...)
);
2. 竞态条件问题
typescript
// Bug: Concurrent operations conflict
async function createTerminal() {
  if (isCreating) return; // Insufficient guard
  isCreating = true;
  // ... creation logic
}

// Fix: Use atomic operation pattern
private creationPromise: Promise<void> | null = null;

async function createTerminal(): Promise<void> {
  if (this.creationPromise) {
    return this.creationPromise;
  }
  this.creationPromise = this.doCreateTerminal();
  try {
    await this.creationPromise;
  } finally {
    this.creationPromise = null;
  }
}
3. WebView消息时序问题
typescript
// Bug: Message sent before WebView ready
panel.webview.postMessage({ type: 'init', data });

// Fix: Wait for ready signal
panel.webview.onDidReceiveMessage(msg => {
  if (msg.type === 'ready') {
    panel.webview.postMessage({ type: 'init', data });
  }
});
4. 空值/未定义引用问题
typescript
// Bug: Assuming object exists
const terminal = this.terminals.get(id);
terminal.write(data); // Crash if undefined!

// Fix: Defensive access with early return
const terminal = this.terminals.get(id);
if (!terminal) {
  console.warn(`Terminal ${id} not found`);
  return;
}
terminal.write(data);
5. Async/Await错误处理问题
typescript
// Bug: Unhandled promise rejection
someAsyncFunction(); // No await, no catch!

// Fix: Proper error handling
try {
  await someAsyncFunction();
} catch (error) {
  vscode.window.showErrorMessage(`Operation failed: ${error.message}`);
}

Phase 3: Fix Implementation

阶段3:修复实现

Fix Implementation Checklist

修复实施检查清单

  • Identify all affected code paths
  • Consider edge cases and error scenarios
  • Maintain backward compatibility
  • Add defensive null checks
  • Ensure proper error handling
  • Register all disposables
  • Add logging for debugging
  • Consider performance impact
  • 确定所有受影响的代码路径
  • 考虑边缘情况与错误场景
  • 保持向后兼容性
  • 添加防御性空值检查
  • 确保正确的错误处理
  • 注册所有可释放资源
  • 添加调试日志
  • 考虑性能影响

Safe Fix Patterns

安全修复模式

Pattern 1: Guard Clause
typescript
async function processTerminal(id: number): Promise<void> {
  // Early validation
  if (id < 1 || id > MAX_TERMINALS) {
    throw new Error(`Invalid terminal ID: ${id}`);
  }

  const terminal = this.getTerminal(id);
  if (!terminal) {
    console.warn(`Terminal ${id} not found, skipping`);
    return;
  }

  // Safe to proceed
  await terminal.process();
}
Pattern 2: Try-Catch-Finally
typescript
async function safeOperation(): Promise<void> {
  const resource = await acquireResource();
  try {
    await performOperation(resource);
  } catch (error) {
    await handleError(error);
    throw error; // Re-throw after logging
  } finally {
    await releaseResource(resource); // Always cleanup
  }
}
Pattern 3: Timeout Protection
typescript
async function operationWithTimeout<T>(
  operation: Promise<T>,
  timeoutMs: number
): Promise<T> {
  const timeout = new Promise<never>((_, reject) =>
    setTimeout(() => reject(new Error('Operation timed out')), timeoutMs)
  );
  return Promise.race([operation, timeout]);
}
模式1:守卫子句
typescript
async function processTerminal(id: number): Promise<void> {
  // Early validation
  if (id < 1 || id > MAX_TERMINALS) {
    throw new Error(`Invalid terminal ID: ${id}`);
  }

  const terminal = this.getTerminal(id);
  if (!terminal) {
    console.warn(`Terminal ${id} not found, skipping`);
    return;
  }

  // Safe to proceed
  await terminal.process();
}
模式2:Try-Catch-Finally
typescript
async function safeOperation(): Promise<void> {
  const resource = await acquireResource();
  try {
    await performOperation(resource);
  } catch (error) {
    await handleError(error);
    throw error; // Re-throw after logging
  } finally {
    await releaseResource(resource); // Always cleanup
  }
}
模式3:超时保护
typescript
async function operationWithTimeout<T>(
  operation: Promise<T>,
  timeoutMs: number
): Promise<T> {
  const timeout = new Promise<never>((_, reject) =>
    setTimeout(() => reject(new Error('Operation timed out')), timeoutMs)
  );
  return Promise.race([operation, timeout]);
}

Phase 4: Verification

阶段4:验证

Testing Strategy

测试策略

  1. Unit Test the Fix
typescript
describe('Bug Fix: Terminal creation race condition', () => {
  it('should handle concurrent creation requests', async () => {
    const manager = new TerminalManager();

    // Simulate concurrent requests
    const results = await Promise.all([
      manager.createTerminal(),
      manager.createTerminal(),
      manager.createTerminal()
    ]);

    // Verify only expected terminals created
    expect(manager.getTerminalCount()).toBe(expectedCount);
  });
});
  1. Integration Test
    • Test the actual user workflow
    • Verify fix in different scenarios
    • Check for regressions
  2. Manual Verification
    • Follow original reproduction steps
    • Verify error no longer occurs
    • Test related functionality
  1. 单元测试修复
typescript
describe('Bug Fix: Terminal creation race condition', () => {
  it('should handle concurrent creation requests', async () => {
    const manager = new TerminalManager();

    // Simulate concurrent requests
    const results = await Promise.all([
      manager.createTerminal(),
      manager.createTerminal(),
      manager.createTerminal()
    ]);

    // Verify only expected terminals created
    expect(manager.getTerminalCount()).toBe(expectedCount);
  });
});
  1. 集成测试
    • 测试实际用户流程
    • 在不同场景下验证修复效果
    • 检查是否存在回归
  2. 手动验证
    • 按照原始复现步骤操作
    • 验证错误不再出现
    • 测试相关功能

Common Bug Categories

常见Bug类别

Memory Leaks

内存泄漏

Detection
typescript
// Add disposal tracking
class ResourceManager implements vscode.Disposable {
  private disposables: vscode.Disposable[] = [];
  private disposed = false;

  register(disposable: vscode.Disposable): void {
    if (this.disposed) {
      disposable.dispose();
      console.warn('Attempted to register after disposal');
      return;
    }
    this.disposables.push(disposable);
  }

  dispose(): void {
    if (this.disposed) return;
    this.disposed = true;

    // LIFO disposal order
    while (this.disposables.length) {
      const d = this.disposables.pop();
      try {
        d?.dispose();
      } catch (e) {
        console.error('Dispose error:', e);
      }
    }
  }
}
Common Causes
  • Event listeners not removed
  • Timers not cleared
  • WebView panels not disposed
  • File watchers not stopped
检测
typescript
// Add disposal tracking
class ResourceManager implements vscode.Disposable {
  private disposables: vscode.Disposable[] = [];
  private disposed = false;

  register(disposable: vscode.Disposable): void {
    if (this.disposed) {
      disposable.dispose();
      console.warn('Attempted to register after disposal');
      return;
    }
    this.disposables.push(disposable);
  }

  dispose(): void {
    if (this.disposed) return;
    this.disposed = true;

    // LIFO disposal order
    while (this.disposables.length) {
      const d = this.disposables.pop();
      try {
        d?.dispose();
      } catch (e) {
        console.error('Dispose error:', e);
      }
    }
  }
}
常见原因
  • 事件监听器未移除
  • 定时器未清除
  • WebView面板未释放
  • 文件监视器未停止

WebView Issues

WebView问题

Communication Failures
typescript
// Implement message queue for reliability
class MessageQueue {
  private queue: Message[] = [];
  private ready = false;

  setReady(): void {
    this.ready = true;
    this.flush();
  }

  send(message: Message): void {
    if (this.ready) {
      this.webview.postMessage(message);
    } else {
      this.queue.push(message);
    }
  }

  private flush(): void {
    while (this.queue.length) {
      this.webview.postMessage(this.queue.shift()!);
    }
  }
}
Rendering Problems
  • Check CSP (Content Security Policy)
  • Verify resource URIs use webview.asWebviewUri()
  • Ensure styles load correctly
  • Check for JavaScript errors in WebView DevTools
通信失败
typescript
// Implement message queue for reliability
class MessageQueue {
  private queue: Message[] = [];
  private ready = false;

  setReady(): void {
    this.ready = true;
    this.flush();
  }

  send(message: Message): void {
    if (this.ready) {
      this.webview.postMessage(message);
    } else {
      this.queue.push(message);
    }
  }

  private flush(): void {
    while (this.queue.length) {
      this.webview.postMessage(this.queue.shift()!);
    }
  }
}
渲染问题
  • 检查CSP(内容安全策略)
  • 验证资源URI使用webview.asWebviewUri()
  • 确保样式正确加载
  • 检查WebView开发者工具中的JavaScript错误

Activation Issues

激活问题

Debugging Activation
typescript
export async function activate(context: vscode.ExtensionContext) {
  console.log('[Extension] Activation started');

  try {
    // Initialize services
    await initializeServices(context);
    console.log('[Extension] Services initialized');

    // Register commands
    registerCommands(context);
    console.log('[Extension] Commands registered');

    console.log('[Extension] Activation complete');
  } catch (error) {
    console.error('[Extension] Activation failed:', error);
    vscode.window.showErrorMessage(
      `Extension activation failed: ${error.message}`
    );
    throw error;
  }
}
Common Causes
  • Incorrect activation events in package.json
  • Exceptions during initialization
  • Missing dependencies
  • Circular imports
调试激活过程
typescript
export async function activate(context: vscode.ExtensionContext) {
  console.log('[Extension] Activation started');

  try {
    // Initialize services
    await initializeServices(context);
    console.log('[Extension] Services initialized');

    // Register commands
    registerCommands(context);
    console.log('[Extension] Commands registered');

    console.log('[Extension] Activation complete');
  } catch (error) {
    console.error('[Extension] Activation failed:', error);
    vscode.window.showErrorMessage(
      `Extension activation failed: ${error.message}`
    );
    throw error;
  }
}
常见原因
  • package.json中的激活事件配置错误
  • 初始化过程中出现异常
  • 缺少依赖项
  • 循环导入

TypeScript Errors

TypeScript错误

Type Safety Fixes
typescript
// Bug: Implicit any and unsafe access
function processData(data) {
  return data.items.map(item => item.value);
}

// Fix: Explicit types and null safety
interface DataItem {
  value: string;
}

interface Data {
  items?: DataItem[];
}

function processData(data: Data): string[] {
  return data.items?.map(item => item.value) ?? [];
}
类型安全修复
typescript
// Bug: Implicit any and unsafe access
function processData(data) {
  return data.items.map(item => item.value);
}

// Fix: Explicit types and null safety
interface DataItem {
  value: string;
}

interface Data {
  items?: DataItem[];
}

function processData(data: Data): string[] {
  return data.items?.map(item => item.value) ?? [];
}

Debugging Tools

调试工具

VS Code Built-in

VS Code内置工具

  1. Extension Development Host
    • F5 to launch debug session
    • Set breakpoints in extension code
    • Inspect variables and call stack
  2. Developer Tools
    • Help > Toggle Developer Tools
    • Console for extension host logs
    • Network tab for WebView resources
  3. WebView Developer Tools
    • Command Palette: "Developer: Open WebView Developer Tools"
    • Debug WebView JavaScript
    • Inspect DOM and styles
  1. 扩展开发宿主
    • 按F5启动调试会话
    • 在扩展代码中设置断点
    • 检查变量与调用栈
  2. 开发者工具
    • 帮助 > 切换开发者工具
    • 控制台查看扩展宿主日志
    • 网络面板查看WebView资源
  3. WebView开发者工具
    • 命令面板:“开发者:打开WebView开发者工具”
    • 调试WebView中的JavaScript
    • 检查DOM与样式

Extension-Specific Debug Panel

扩展专用调试面板

typescript
// Terminal State Debug Panel (Ctrl+Shift+D)
// Monitors: system state, terminal info, performance metrics
typescript
// Terminal State Debug Panel (Ctrl+Shift+D)
// Monitors: system state, terminal info, performance metrics

Logging Best Practices

日志最佳实践

typescript
// Structured logging with context
const logger = {
  debug: (component: string, message: string, data?: object) => {
    if (debugEnabled) {
      console.log(`[${component}] ${message}`, data ?? '');
    }
  },
  error: (component: string, message: string, error: Error) => {
    console.error(`[${component}] ${message}:`, {
      message: error.message,
      stack: error.stack
    });
  }
};
typescript
// Structured logging with context
const logger = {
  debug: (component: string, message: string, data?: object) => {
    if (debugEnabled) {
      console.log(`[${component}] ${message}`, data ?? '');
    }
  },
  error: (component: string, message: string, error: Error) => {
    console.error(`[${component}] ${message}:`, {
      message: error.message,
      stack: error.stack
    });
  }
};

Prevention Strategies

预防策略

Code Review Checklist

代码审查检查清单

  • All disposables registered in subscriptions
  • Async operations have error handling
  • Null checks for optional data
  • No race conditions in concurrent operations
  • WebView messages validated
  • Timeouts for long-running operations
  • Graceful degradation on failures
  • 所有可释放资源均已注册到订阅中
  • 异步操作具备错误处理
  • 对可选数据进行空值检查
  • 并发操作中无竞态条件
  • WebView消息已验证
  • 长时间操作设置超时保护
  • 故障时优雅降级

Testing Requirements

测试要求

  • Unit tests for fixed functionality
  • Regression tests for bug scenarios
  • Integration tests for affected workflows
  • Memory leak tests for resource management
  • 为修复的功能编写单元测试
  • 为bug场景编写回归测试
  • 对受影响的工作流进行集成测试
  • 对资源管理进行内存泄漏测试

Resources

资源

For detailed reference documentation:
  • references/common-bugs.md
    - Catalog of common VS Code extension bugs
  • references/debugging-tools.md
    - Comprehensive debugging tool guide
  • references/fix-patterns.md
    - Proven fix implementation patterns
如需详细参考文档:
  • references/common-bugs.md
    - VS Code扩展常见bug目录
  • references/debugging-tools.md
    - 全面的调试工具指南
  • references/fix-patterns.md
    - 经过验证的修复实现模式