调试器 API
概述
Trae 调试器 API 提供了完整的调试功能,支持多种编程语言和调试协议。开发者可以通过 API 创建自定义调试器、设置断点、检查变量、控制程序执行流程等。
核心概念
调试会话
调试会话是调试器的核心概念,代表一个正在进行的调试过程:
typescript
interface DebugSession {
id: string;
name: string;
type: string;
configuration: DebugConfiguration;
workspaceFolder?: WorkspaceFolder;
}
interface DebugConfiguration {
type: string;
name: string;
request: 'launch' | 'attach';
program?: string;
args?: string[];
env?: { [key: string]: string };
cwd?: string;
[key: string]: any;
}调试适配器
typescript
interface DebugAdapter {
type: string;
executable: DebugAdapterExecutable;
server?: DebugAdapterServer;
}
interface DebugAdapterExecutable {
command: string;
args?: string[];
options?: {
env?: { [key: string]: string };
cwd?: string;
};
}API 参考
调试会话管理
startDebugging()
启动调试会话:
typescript
import { debug, DebugConfiguration } from '@trae/api';
// 启动 Node.js 调试会话
const config: DebugConfiguration = {
type: 'node',
request: 'launch',
name: 'Launch Program',
program: '${workspaceFolder}/app.js',
args: ['--port', '3000'],
env: {
NODE_ENV: 'development'
},
cwd: '${workspaceFolder}',
console: 'integratedTerminal'
};
const success = await debug.startDebugging(undefined, config);
if (success) {
console.log('Debugging started successfully');
}stopDebugging()
停止调试会话:
typescript
// 停止当前活动的调试会话
if (debug.activeDebugSession) {
await debug.stopDebugging(debug.activeDebugSession);
}
// 停止所有调试会话
for (const session of debug.debugSessions) {
await debug.stopDebugging(session);
}断点管理
addBreakpoints()
添加断点:
typescript
import { debug, Breakpoint, SourceBreakpoint } from '@trae/api';
// 添加源码断点
const sourceBreakpoint = new SourceBreakpoint(
new Location(uri, new Position(10, 0)), // 第11行
true, // 启用
'x > 5' // 条件
);
debug.addBreakpoints([sourceBreakpoint]);
// 添加函数断点
const functionBreakpoint = new FunctionBreakpoint(
'myFunction',
true,
'arguments.length > 0'
);
debug.addBreakpoints([functionBreakpoint]);removeBreakpoints()
移除断点:
typescript
// 移除特定断点
debug.removeBreakpoints([sourceBreakpoint]);
// 移除所有断点
const allBreakpoints = debug.breakpoints;
debug.removeBreakpoints(allBreakpoints);调试控制
执行控制命令
typescript
// 继续执行
await debug.activeDebugSession?.customRequest('continue');
// 单步执行
await debug.activeDebugSession?.customRequest('next');
// 步入函数
await debug.activeDebugSession?.customRequest('stepIn');
// 步出函数
await debug.activeDebugSession?.customRequest('stepOut');
// 暂停执行
await debug.activeDebugSession?.customRequest('pause');
// 重启调试
await debug.activeDebugSession?.customRequest('restart');变量检查
getVariables()
获取变量信息:
typescript
// 获取当前作用域的变量
const getVariables = async (session: DebugSession) => {
try {
const response = await session.customRequest('scopes', {
frameId: 0
});
const scopes = response.scopes;
const variables = [];
for (const scope of scopes) {
const varsResponse = await session.customRequest('variables', {
variablesReference: scope.variablesReference
});
variables.push(...varsResponse.variables);
}
return variables;
} catch (error) {
console.error('Failed to get variables:', error);
return [];
}
};evaluateExpression()
评估表达式:
typescript
const evaluateExpression = async (expression: string) => {
if (!debug.activeDebugSession) {
return null;
}
try {
const response = await debug.activeDebugSession.customRequest('evaluate', {
expression,
frameId: 0,
context: 'watch'
});
return {
result: response.result,
type: response.type,
variablesReference: response.variablesReference
};
} catch (error) {
console.error('Failed to evaluate expression:', error);
return null;
}
};调用堆栈
getStackTrace()
获取调用堆栈:
typescript
const getStackTrace = async (session: DebugSession) => {
try {
const response = await session.customRequest('stackTrace', {
threadId: 1,
startFrame: 0,
levels: 20
});
return response.stackFrames.map(frame => ({
id: frame.id,
name: frame.name,
source: frame.source,
line: frame.line,
column: frame.column
}));
} catch (error) {
console.error('Failed to get stack trace:', error);
return [];
}
};调试适配器
注册调试适配器
registerDebugAdapterDescriptorFactory()
typescript
import { debug, DebugAdapterDescriptorFactory } from '@trae/api';
class MyDebugAdapterFactory implements DebugAdapterDescriptorFactory {
createDebugAdapterDescriptor(
session: DebugSession,
executable: DebugAdapterExecutable | undefined
) {
// 返回调试适配器描述符
return new DebugAdapterExecutable(
'node',
['path/to/debug-adapter.js'],
{
env: { DEBUG: 'true' }
}
);
}
}
// 注册工厂
const disposable = debug.registerDebugAdapterDescriptorFactory(
'myLanguage',
new MyDebugAdapterFactory()
);自定义调试适配器
typescript
class CustomDebugAdapter {
private session: DebugSession;
constructor(session: DebugSession) {
this.session = session;
}
async initialize() {
// 初始化调试适配器
await this.session.customRequest('initialize', {
clientID: 'trae',
clientName: 'Trae IDE',
adapterID: 'custom',
pathFormat: 'path',
linesStartAt1: true,
columnsStartAt1: true,
supportsVariableType: true,
supportsVariablePaging: true,
supportsRunInTerminalRequest: true
});
}
async launch(config: DebugConfiguration) {
// 启动程序
await this.session.customRequest('launch', config);
}
async attach(config: DebugConfiguration) {
// 附加到进程
await this.session.customRequest('attach', config);
}
}事件处理
调试事件监听
typescript
// 监听调试会话开始
debug.onDidStartDebugSession(session => {
console.log(`Debug session started: ${session.name}`);
// 设置初始断点
setupInitialBreakpoints(session);
});
// 监听调试会话结束
debug.onDidTerminateDebugSession(session => {
console.log(`Debug session terminated: ${session.name}`);
// 清理资源
cleanupDebugResources(session);
});
// 监听调试会话变化
debug.onDidChangeActiveDebugSession(session => {
if (session) {
console.log(`Active debug session changed to: ${session.name}`);
updateDebugUI(session);
}
});
// 监听断点变化
debug.onDidChangeBreakpoints(event => {
console.log('Breakpoints changed:', {
added: event.added,
removed: event.removed,
changed: event.changed
});
});自定义调试事件
typescript
// 处理自定义调试协议事件
const handleCustomEvents = (session: DebugSession) => {
session.customRequest('setExceptionBreakpoints', {
filters: ['uncaught', 'caught']
});
// 监听输出事件
session.onDidReceiveDebugSessionCustomEvent(event => {
if (event.event === 'output') {
console.log('Debug output:', event.body.output);
}
if (event.event === 'stopped') {
console.log('Execution stopped:', event.body.reason);
handleExecutionStopped(session, event.body);
}
});
};高级功能
多线程调试
typescript
const handleMultiThreadDebugging = async (session: DebugSession) => {
try {
// 获取所有线程
const threadsResponse = await session.customRequest('threads');
const threads = threadsResponse.threads;
console.log('Available threads:', threads);
// 为每个线程获取堆栈跟踪
for (const thread of threads) {
const stackTrace = await session.customRequest('stackTrace', {
threadId: thread.id
});
console.log(`Thread ${thread.id} stack:`, stackTrace.stackFrames);
}
} catch (error) {
console.error('Multi-thread debugging error:', error);
}
};条件断点
typescript
const setConditionalBreakpoint = (uri: Uri, line: number, condition: string) => {
const breakpoint = new SourceBreakpoint(
new Location(uri, new Position(line, 0)),
true,
condition
);
debug.addBreakpoints([breakpoint]);
};
// 示例:设置条件断点
setConditionalBreakpoint(
Uri.file('/path/to/file.js'),
15,
'user.age > 18 && user.isActive'
);日志点
typescript
const setLogPoint = (uri: Uri, line: number, logMessage: string) => {
const breakpoint = new SourceBreakpoint(
new Location(uri, new Position(line, 0)),
true,
undefined,
undefined,
logMessage
);
debug.addBreakpoints([breakpoint]);
};
// 示例:设置日志点
setLogPoint(
Uri.file('/path/to/file.js'),
20,
'User ID: {userId}, Name: {user.name}'
);调试配置
预定义配置
typescript
// Node.js 调试配置
const nodeConfig: DebugConfiguration = {
type: 'node',
request: 'launch',
name: 'Launch Node.js',
program: '${workspaceFolder}/index.js',
args: [],
env: {},
console: 'integratedTerminal',
internalConsoleOptions: 'neverOpen',
skipFiles: ['<node_internals>/**']
};
// Python 调试配置
const pythonConfig: DebugConfiguration = {
type: 'python',
request: 'launch',
name: 'Launch Python',
program: '${workspaceFolder}/main.py',
args: [],
console: 'integratedTerminal',
justMyCode: true
};
// Chrome 调试配置
const chromeConfig: DebugConfiguration = {
type: 'chrome',
request: 'launch',
name: 'Launch Chrome',
url: 'http://localhost:3000',
webRoot: '${workspaceFolder}/src',
sourceMaps: true
};动态配置
typescript
const createDynamicConfig = (projectType: string): DebugConfiguration => {
const baseConfig = {
name: `Debug ${projectType}`,
request: 'launch' as const,
cwd: '${workspaceFolder}'
};
switch (projectType) {
case 'react':
return {
...baseConfig,
type: 'chrome',
url: 'http://localhost:3000',
webRoot: '${workspaceFolder}/src'
};
case 'express':
return {
...baseConfig,
type: 'node',
program: '${workspaceFolder}/server.js',
env: { NODE_ENV: 'development' }
};
default:
throw new Error(`Unsupported project type: ${projectType}`);
}
};错误处理
typescript
const robustDebugSession = async (config: DebugConfiguration) => {
try {
const success = await debug.startDebugging(undefined, config);
if (!success) {
throw new Error('Failed to start debugging session');
}
// 设置错误处理
debug.activeDebugSession?.onDidReceiveDebugSessionCustomEvent(event => {
if (event.event === 'error') {
console.error('Debug session error:', event.body);
handleDebugError(event.body);
}
});
} catch (error) {
console.error('Debug session failed:', error);
showDebugErrorMessage(error.message);
}
};
const handleDebugError = (error: any) => {
// 根据错误类型采取不同的处理策略
switch (error.type) {
case 'connection_failed':
// 尝试重新连接
retryConnection();
break;
case 'breakpoint_failed':
// 移除有问题的断点
removeProblematicBreakpoints();
break;
default:
// 通用错误处理
logError(error);
}
};性能优化
延迟加载
typescript
const lazyDebugAdapter = {
async createDebugAdapterDescriptor(session: DebugSession) {
// 延迟加载调试适配器
const { DebugAdapter } = await import('./debug-adapter');
return new DebugAdapter(session);
}
};缓存优化
typescript
const debugCache = new Map();
const getCachedVariables = async (session: DebugSession, frameId: number) => {
const cacheKey = `${session.id}:${frameId}`;
if (debugCache.has(cacheKey)) {
return debugCache.get(cacheKey);
}
const variables = await getVariables(session, frameId);
debugCache.set(cacheKey, variables);
return variables;
};