xdebug-mcp 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +341 -0
- package/dist/config.d.ts +36 -0
- package/dist/config.js +47 -0
- package/dist/config.js.map +1 -0
- package/dist/dbgp/connection.d.ts +52 -0
- package/dist/dbgp/connection.js +362 -0
- package/dist/dbgp/connection.js.map +1 -0
- package/dist/dbgp/index.d.ts +3 -0
- package/dist/dbgp/index.js +4 -0
- package/dist/dbgp/index.js.map +1 -0
- package/dist/dbgp/server.d.ts +34 -0
- package/dist/dbgp/server.js +94 -0
- package/dist/dbgp/server.js.map +1 -0
- package/dist/dbgp/types.d.ts +112 -0
- package/dist/dbgp/types.js +28 -0
- package/dist/dbgp/types.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +93 -0
- package/dist/index.js.map +1 -0
- package/dist/session/code-coverage.d.ts +94 -0
- package/dist/session/code-coverage.js +226 -0
- package/dist/session/code-coverage.js.map +1 -0
- package/dist/session/debug-config.d.ts +102 -0
- package/dist/session/debug-config.js +194 -0
- package/dist/session/debug-config.js.map +1 -0
- package/dist/session/index.d.ts +10 -0
- package/dist/session/index.js +11 -0
- package/dist/session/index.js.map +1 -0
- package/dist/session/logpoint-manager.d.ts +94 -0
- package/dist/session/logpoint-manager.js +167 -0
- package/dist/session/logpoint-manager.js.map +1 -0
- package/dist/session/manager.d.ts +41 -0
- package/dist/session/manager.js +135 -0
- package/dist/session/manager.js.map +1 -0
- package/dist/session/profiler.d.ts +89 -0
- package/dist/session/profiler.js +191 -0
- package/dist/session/profiler.js.map +1 -0
- package/dist/session/request-context.d.ts +50 -0
- package/dist/session/request-context.js +182 -0
- package/dist/session/request-context.js.map +1 -0
- package/dist/session/session-export.d.ts +83 -0
- package/dist/session/session-export.js +320 -0
- package/dist/session/session-export.js.map +1 -0
- package/dist/session/session.d.ts +92 -0
- package/dist/session/session.js +369 -0
- package/dist/session/session.js.map +1 -0
- package/dist/session/step-filter.d.ts +81 -0
- package/dist/session/step-filter.js +174 -0
- package/dist/session/step-filter.js.map +1 -0
- package/dist/session/watch-manager.d.ts +64 -0
- package/dist/session/watch-manager.js +137 -0
- package/dist/session/watch-manager.js.map +1 -0
- package/dist/tools/advanced.d.ts +26 -0
- package/dist/tools/advanced.js +502 -0
- package/dist/tools/advanced.js.map +1 -0
- package/dist/tools/breakpoints.d.ts +6 -0
- package/dist/tools/breakpoints.js +308 -0
- package/dist/tools/breakpoints.js.map +1 -0
- package/dist/tools/execution.d.ts +6 -0
- package/dist/tools/execution.js +283 -0
- package/dist/tools/execution.js.map +1 -0
- package/dist/tools/index.d.ts +31 -0
- package/dist/tools/index.js +44 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/inspection.d.ts +7 -0
- package/dist/tools/inspection.js +431 -0
- package/dist/tools/inspection.js.map +1 -0
- package/dist/tools/session.d.ts +6 -0
- package/dist/tools/session.js +164 -0
- package/dist/tools/session.js.map +1 -0
- package/dist/utils/logger.d.ts +16 -0
- package/dist/utils/logger.js +47 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/path-mapper.d.ts +13 -0
- package/dist/utils/path-mapper.js +56 -0
- package/dist/utils/path-mapper.js.map +1 -0
- package/package.json +56 -0
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Debug Session
|
|
3
|
+
* Represents a single PHP debug session with all debugging operations.
|
|
4
|
+
*/
|
|
5
|
+
import { EventEmitter } from 'events';
|
|
6
|
+
import { logger } from '../utils/logger.js';
|
|
7
|
+
export class DebugSession extends EventEmitter {
|
|
8
|
+
connection;
|
|
9
|
+
id;
|
|
10
|
+
status = 'starting';
|
|
11
|
+
currentFile;
|
|
12
|
+
currentLine;
|
|
13
|
+
startTime;
|
|
14
|
+
breakpoints = new Map();
|
|
15
|
+
initialized = false;
|
|
16
|
+
constructor(connection) {
|
|
17
|
+
super();
|
|
18
|
+
this.connection = connection;
|
|
19
|
+
this.id = connection.id;
|
|
20
|
+
this.startTime = new Date();
|
|
21
|
+
// Update state on responses
|
|
22
|
+
connection.on('response', (response) => {
|
|
23
|
+
if (response.status) {
|
|
24
|
+
this.status = response.status;
|
|
25
|
+
}
|
|
26
|
+
if (response.message) {
|
|
27
|
+
this.currentFile = response.message.filename;
|
|
28
|
+
this.currentLine = response.message.lineno;
|
|
29
|
+
}
|
|
30
|
+
this.emit('stateChange', this.getState());
|
|
31
|
+
});
|
|
32
|
+
connection.on('close', () => {
|
|
33
|
+
this.status = 'stopped';
|
|
34
|
+
this.emit('close');
|
|
35
|
+
});
|
|
36
|
+
connection.on('stream', (data) => {
|
|
37
|
+
this.emit('output', data);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
get initPacket() {
|
|
41
|
+
return this.connection.initPacket;
|
|
42
|
+
}
|
|
43
|
+
getState() {
|
|
44
|
+
return {
|
|
45
|
+
id: this.id,
|
|
46
|
+
status: this.status,
|
|
47
|
+
filename: this.currentFile,
|
|
48
|
+
lineno: this.currentLine,
|
|
49
|
+
ideKey: this.initPacket?.ideKey,
|
|
50
|
+
startTime: this.startTime,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
// === Initialization ===
|
|
54
|
+
async initialize() {
|
|
55
|
+
if (this.initialized)
|
|
56
|
+
return;
|
|
57
|
+
try {
|
|
58
|
+
// Set preferred features
|
|
59
|
+
await this.setFeature('max_depth', '3');
|
|
60
|
+
await this.setFeature('max_children', '128');
|
|
61
|
+
await this.setFeature('max_data', '2048');
|
|
62
|
+
await this.setFeature('show_hidden', '1');
|
|
63
|
+
this.initialized = true;
|
|
64
|
+
logger.debug(`Session ${this.id} initialized`);
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
logger.error(`Failed to initialize session ${this.id}:`, error);
|
|
68
|
+
throw error;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// === Feature Negotiation ===
|
|
72
|
+
async setFeature(name, value) {
|
|
73
|
+
try {
|
|
74
|
+
const response = await this.connection.sendCommand('feature_set', {
|
|
75
|
+
n: name,
|
|
76
|
+
v: value,
|
|
77
|
+
});
|
|
78
|
+
return response.success === true;
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
async getFeature(name) {
|
|
85
|
+
try {
|
|
86
|
+
const response = await this.connection.sendCommand('feature_get', {
|
|
87
|
+
n: name,
|
|
88
|
+
});
|
|
89
|
+
const data = response.data;
|
|
90
|
+
return data['@_supported'] === '1' ? data['#text'] || null : null;
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// === Breakpoint Operations ===
|
|
97
|
+
async setLineBreakpoint(filename, line, options) {
|
|
98
|
+
const args = {
|
|
99
|
+
t: options?.condition ? 'conditional' : 'line',
|
|
100
|
+
f: this.normalizeFileUri(filename),
|
|
101
|
+
n: line.toString(),
|
|
102
|
+
};
|
|
103
|
+
if (options?.hitValue !== undefined) {
|
|
104
|
+
args['h'] = options.hitValue.toString();
|
|
105
|
+
}
|
|
106
|
+
if (options?.hitCondition) {
|
|
107
|
+
args['o'] = options.hitCondition;
|
|
108
|
+
}
|
|
109
|
+
if (options?.temporary) {
|
|
110
|
+
args['r'] = '1';
|
|
111
|
+
}
|
|
112
|
+
const response = await this.connection.sendCommand('breakpoint_set', args, options?.condition);
|
|
113
|
+
if (response.error) {
|
|
114
|
+
throw new Error(`Failed to set breakpoint: ${response.error.message}`);
|
|
115
|
+
}
|
|
116
|
+
const result = this.connection.parseBreakpointSet(response);
|
|
117
|
+
const breakpoint = {
|
|
118
|
+
id: result.id,
|
|
119
|
+
type: options?.condition ? 'conditional' : 'line',
|
|
120
|
+
state: 'enabled',
|
|
121
|
+
resolved: result.resolved,
|
|
122
|
+
filename,
|
|
123
|
+
lineno: line,
|
|
124
|
+
expression: options?.condition,
|
|
125
|
+
hitValue: options?.hitValue,
|
|
126
|
+
hitCondition: options?.hitCondition,
|
|
127
|
+
};
|
|
128
|
+
this.breakpoints.set(breakpoint.id, breakpoint);
|
|
129
|
+
logger.debug(`Breakpoint set: ${breakpoint.id} at ${filename}:${line}`);
|
|
130
|
+
return breakpoint;
|
|
131
|
+
}
|
|
132
|
+
async setExceptionBreakpoint(exception = '*') {
|
|
133
|
+
const response = await this.connection.sendCommand('breakpoint_set', {
|
|
134
|
+
t: 'exception',
|
|
135
|
+
x: exception,
|
|
136
|
+
});
|
|
137
|
+
if (response.error) {
|
|
138
|
+
throw new Error(`Failed to set exception breakpoint: ${response.error.message}`);
|
|
139
|
+
}
|
|
140
|
+
const result = this.connection.parseBreakpointSet(response);
|
|
141
|
+
const breakpoint = {
|
|
142
|
+
id: result.id,
|
|
143
|
+
type: 'exception',
|
|
144
|
+
state: 'enabled',
|
|
145
|
+
exception,
|
|
146
|
+
};
|
|
147
|
+
this.breakpoints.set(breakpoint.id, breakpoint);
|
|
148
|
+
return breakpoint;
|
|
149
|
+
}
|
|
150
|
+
async setCallBreakpoint(functionName) {
|
|
151
|
+
const response = await this.connection.sendCommand('breakpoint_set', {
|
|
152
|
+
t: 'call',
|
|
153
|
+
m: functionName,
|
|
154
|
+
});
|
|
155
|
+
if (response.error) {
|
|
156
|
+
throw new Error(`Failed to set call breakpoint: ${response.error.message}`);
|
|
157
|
+
}
|
|
158
|
+
const result = this.connection.parseBreakpointSet(response);
|
|
159
|
+
const breakpoint = {
|
|
160
|
+
id: result.id,
|
|
161
|
+
type: 'call',
|
|
162
|
+
state: 'enabled',
|
|
163
|
+
function: functionName,
|
|
164
|
+
};
|
|
165
|
+
this.breakpoints.set(breakpoint.id, breakpoint);
|
|
166
|
+
return breakpoint;
|
|
167
|
+
}
|
|
168
|
+
async removeBreakpoint(breakpointId) {
|
|
169
|
+
const response = await this.connection.sendCommand('breakpoint_remove', {
|
|
170
|
+
d: breakpointId,
|
|
171
|
+
});
|
|
172
|
+
if (!response.error) {
|
|
173
|
+
this.breakpoints.delete(breakpointId);
|
|
174
|
+
logger.debug(`Breakpoint removed: ${breakpointId}`);
|
|
175
|
+
return true;
|
|
176
|
+
}
|
|
177
|
+
return false;
|
|
178
|
+
}
|
|
179
|
+
async updateBreakpoint(breakpointId, options) {
|
|
180
|
+
const args = { d: breakpointId };
|
|
181
|
+
if (options.state)
|
|
182
|
+
args['s'] = options.state;
|
|
183
|
+
if (options.hitValue !== undefined)
|
|
184
|
+
args['h'] = options.hitValue.toString();
|
|
185
|
+
if (options.hitCondition)
|
|
186
|
+
args['o'] = options.hitCondition;
|
|
187
|
+
const response = await this.connection.sendCommand('breakpoint_update', args);
|
|
188
|
+
return !response.error;
|
|
189
|
+
}
|
|
190
|
+
async getBreakpoint(breakpointId) {
|
|
191
|
+
const response = await this.connection.sendCommand('breakpoint_get', {
|
|
192
|
+
d: breakpointId,
|
|
193
|
+
});
|
|
194
|
+
if (response.error)
|
|
195
|
+
return null;
|
|
196
|
+
const breakpoints = this.connection.parseBreakpoints(response);
|
|
197
|
+
return breakpoints[0] || null;
|
|
198
|
+
}
|
|
199
|
+
async listBreakpoints() {
|
|
200
|
+
const response = await this.connection.sendCommand('breakpoint_list');
|
|
201
|
+
const breakpoints = this.connection.parseBreakpoints(response);
|
|
202
|
+
// Update local cache
|
|
203
|
+
this.breakpoints.clear();
|
|
204
|
+
for (const bp of breakpoints) {
|
|
205
|
+
this.breakpoints.set(bp.id, bp);
|
|
206
|
+
}
|
|
207
|
+
return breakpoints;
|
|
208
|
+
}
|
|
209
|
+
// === Execution Control ===
|
|
210
|
+
async run() {
|
|
211
|
+
const response = await this.connection.sendCommand('run');
|
|
212
|
+
return this.handleStepResponse(response);
|
|
213
|
+
}
|
|
214
|
+
async stepInto() {
|
|
215
|
+
const response = await this.connection.sendCommand('step_into');
|
|
216
|
+
return this.handleStepResponse(response);
|
|
217
|
+
}
|
|
218
|
+
async stepOver() {
|
|
219
|
+
const response = await this.connection.sendCommand('step_over');
|
|
220
|
+
return this.handleStepResponse(response);
|
|
221
|
+
}
|
|
222
|
+
async stepOut() {
|
|
223
|
+
const response = await this.connection.sendCommand('step_out');
|
|
224
|
+
return this.handleStepResponse(response);
|
|
225
|
+
}
|
|
226
|
+
async stop() {
|
|
227
|
+
await this.connection.sendCommand('stop');
|
|
228
|
+
this.status = 'stopped';
|
|
229
|
+
}
|
|
230
|
+
async detach() {
|
|
231
|
+
await this.connection.sendCommand('detach');
|
|
232
|
+
}
|
|
233
|
+
handleStepResponse(response) {
|
|
234
|
+
const status = response.status || 'break';
|
|
235
|
+
this.status = status;
|
|
236
|
+
if (response.message) {
|
|
237
|
+
this.currentFile = response.message.filename;
|
|
238
|
+
this.currentLine = response.message.lineno;
|
|
239
|
+
}
|
|
240
|
+
return {
|
|
241
|
+
status,
|
|
242
|
+
file: this.currentFile,
|
|
243
|
+
line: this.currentLine,
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
// === Stack Inspection ===
|
|
247
|
+
async getStackDepth() {
|
|
248
|
+
const response = await this.connection.sendCommand('stack_depth');
|
|
249
|
+
const data = response.data;
|
|
250
|
+
return parseInt(data['@_depth'] || '0', 10);
|
|
251
|
+
}
|
|
252
|
+
async getStackTrace(depth) {
|
|
253
|
+
const args = {};
|
|
254
|
+
if (depth !== undefined) {
|
|
255
|
+
args['d'] = depth.toString();
|
|
256
|
+
}
|
|
257
|
+
const response = await this.connection.sendCommand('stack_get', args);
|
|
258
|
+
return this.connection.parseStackFrames(response);
|
|
259
|
+
}
|
|
260
|
+
// === Context and Variables ===
|
|
261
|
+
async getContexts(stackDepth = 0) {
|
|
262
|
+
const response = await this.connection.sendCommand('context_names', {
|
|
263
|
+
d: stackDepth.toString(),
|
|
264
|
+
});
|
|
265
|
+
return this.connection.parseContexts(response);
|
|
266
|
+
}
|
|
267
|
+
async getVariables(contextId = 0, stackDepth = 0) {
|
|
268
|
+
const response = await this.connection.sendCommand('context_get', {
|
|
269
|
+
c: contextId.toString(),
|
|
270
|
+
d: stackDepth.toString(),
|
|
271
|
+
});
|
|
272
|
+
return this.connection.parseProperties(response);
|
|
273
|
+
}
|
|
274
|
+
async getVariable(name, options) {
|
|
275
|
+
const args = {
|
|
276
|
+
n: name,
|
|
277
|
+
};
|
|
278
|
+
if (options?.contextId !== undefined) {
|
|
279
|
+
args['c'] = options.contextId.toString();
|
|
280
|
+
}
|
|
281
|
+
if (options?.stackDepth !== undefined) {
|
|
282
|
+
args['d'] = options.stackDepth.toString();
|
|
283
|
+
}
|
|
284
|
+
if (options?.maxDepth !== undefined) {
|
|
285
|
+
args['m'] = options.maxDepth.toString();
|
|
286
|
+
}
|
|
287
|
+
if (options?.page !== undefined) {
|
|
288
|
+
args['p'] = options.page.toString();
|
|
289
|
+
}
|
|
290
|
+
const response = await this.connection.sendCommand('property_get', args);
|
|
291
|
+
if (response.error) {
|
|
292
|
+
return null;
|
|
293
|
+
}
|
|
294
|
+
return this.connection.parseProperty(response);
|
|
295
|
+
}
|
|
296
|
+
async setVariable(name, value, options) {
|
|
297
|
+
const args = {
|
|
298
|
+
n: name,
|
|
299
|
+
};
|
|
300
|
+
if (options?.contextId !== undefined) {
|
|
301
|
+
args['c'] = options.contextId.toString();
|
|
302
|
+
}
|
|
303
|
+
if (options?.stackDepth !== undefined) {
|
|
304
|
+
args['d'] = options.stackDepth.toString();
|
|
305
|
+
}
|
|
306
|
+
if (options?.type) {
|
|
307
|
+
args['t'] = options.type;
|
|
308
|
+
}
|
|
309
|
+
const response = await this.connection.sendCommand('property_set', args, value);
|
|
310
|
+
return response.success === true || !response.error;
|
|
311
|
+
}
|
|
312
|
+
// === Expression Evaluation ===
|
|
313
|
+
async evaluate(expression, stackDepth = 0) {
|
|
314
|
+
const response = await this.connection.sendCommand('eval', { d: stackDepth.toString() }, expression);
|
|
315
|
+
if (response.error) {
|
|
316
|
+
throw new Error(`Evaluation error: ${response.error.message}`);
|
|
317
|
+
}
|
|
318
|
+
return this.connection.parseProperty(response);
|
|
319
|
+
}
|
|
320
|
+
// === Source Code ===
|
|
321
|
+
async getSource(fileUri, beginLine, endLine) {
|
|
322
|
+
const args = {
|
|
323
|
+
f: this.normalizeFileUri(fileUri),
|
|
324
|
+
};
|
|
325
|
+
if (beginLine !== undefined)
|
|
326
|
+
args['b'] = beginLine.toString();
|
|
327
|
+
if (endLine !== undefined)
|
|
328
|
+
args['e'] = endLine.toString();
|
|
329
|
+
const response = await this.connection.sendCommand('source', args);
|
|
330
|
+
if (response.error)
|
|
331
|
+
return null;
|
|
332
|
+
const data = response.data;
|
|
333
|
+
const encoding = data['@_encoding'];
|
|
334
|
+
const content = data['#text'] || '';
|
|
335
|
+
if (encoding === 'base64' && content) {
|
|
336
|
+
return Buffer.from(content, 'base64').toString('utf8');
|
|
337
|
+
}
|
|
338
|
+
return content;
|
|
339
|
+
}
|
|
340
|
+
// === Stream Redirection ===
|
|
341
|
+
async redirectStdout(mode) {
|
|
342
|
+
const modeMap = { disable: '0', copy: '1', redirect: '2' };
|
|
343
|
+
const response = await this.connection.sendCommand('stdout', {
|
|
344
|
+
c: modeMap[mode],
|
|
345
|
+
});
|
|
346
|
+
return response.success === true;
|
|
347
|
+
}
|
|
348
|
+
async redirectStderr(mode) {
|
|
349
|
+
const modeMap = { disable: '0', copy: '1', redirect: '2' };
|
|
350
|
+
const response = await this.connection.sendCommand('stderr', {
|
|
351
|
+
c: modeMap[mode],
|
|
352
|
+
});
|
|
353
|
+
return response.success === true;
|
|
354
|
+
}
|
|
355
|
+
// === Utilities ===
|
|
356
|
+
normalizeFileUri(path) {
|
|
357
|
+
if (path.startsWith('file://')) {
|
|
358
|
+
return path;
|
|
359
|
+
}
|
|
360
|
+
return `file://${path}`;
|
|
361
|
+
}
|
|
362
|
+
close() {
|
|
363
|
+
this.connection.close();
|
|
364
|
+
}
|
|
365
|
+
get isConnected() {
|
|
366
|
+
return this.connection.isConnected;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
//# sourceMappingURL=session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/session/session.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Step Filter
|
|
3
|
+
* Manages step filtering to skip vendor/library code during debugging.
|
|
4
|
+
*/
|
|
5
|
+
export interface StepFilterRule {
|
|
6
|
+
id: string;
|
|
7
|
+
pattern: string;
|
|
8
|
+
type: 'include' | 'exclude';
|
|
9
|
+
enabled: boolean;
|
|
10
|
+
description?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface FunctionCallEntry {
|
|
13
|
+
timestamp: Date;
|
|
14
|
+
name: string;
|
|
15
|
+
file: string;
|
|
16
|
+
line: number;
|
|
17
|
+
depth: number;
|
|
18
|
+
args?: string[];
|
|
19
|
+
}
|
|
20
|
+
export declare class StepFilter {
|
|
21
|
+
private rules;
|
|
22
|
+
private ruleIdCounter;
|
|
23
|
+
private functionHistory;
|
|
24
|
+
private maxHistorySize;
|
|
25
|
+
constructor();
|
|
26
|
+
/**
|
|
27
|
+
* Add a step filter rule
|
|
28
|
+
*/
|
|
29
|
+
addRule(pattern: string, type: 'include' | 'exclude', description?: string): StepFilterRule;
|
|
30
|
+
/**
|
|
31
|
+
* Remove a rule
|
|
32
|
+
*/
|
|
33
|
+
removeRule(id: string): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Enable/disable a rule
|
|
36
|
+
*/
|
|
37
|
+
setRuleEnabled(id: string, enabled: boolean): boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Get all rules
|
|
40
|
+
*/
|
|
41
|
+
getAllRules(): StepFilterRule[];
|
|
42
|
+
/**
|
|
43
|
+
* Check if a file should be skipped during stepping
|
|
44
|
+
*/
|
|
45
|
+
shouldSkip(filePath: string): boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Check if a path matches a pattern
|
|
48
|
+
*/
|
|
49
|
+
private matchesPattern;
|
|
50
|
+
/**
|
|
51
|
+
* Record a function call in history
|
|
52
|
+
*/
|
|
53
|
+
recordFunctionCall(entry: Omit<FunctionCallEntry, 'timestamp'>): void;
|
|
54
|
+
/**
|
|
55
|
+
* Get function call history
|
|
56
|
+
*/
|
|
57
|
+
getFunctionHistory(limit?: number): FunctionCallEntry[];
|
|
58
|
+
/**
|
|
59
|
+
* Clear function history
|
|
60
|
+
*/
|
|
61
|
+
clearHistory(): void;
|
|
62
|
+
/**
|
|
63
|
+
* Search function history
|
|
64
|
+
*/
|
|
65
|
+
searchHistory(query: string): FunctionCallEntry[];
|
|
66
|
+
/**
|
|
67
|
+
* Get function call statistics
|
|
68
|
+
*/
|
|
69
|
+
getCallStatistics(): Map<string, {
|
|
70
|
+
count: number;
|
|
71
|
+
lastCall: Date;
|
|
72
|
+
}>;
|
|
73
|
+
/**
|
|
74
|
+
* Export filter configuration
|
|
75
|
+
*/
|
|
76
|
+
exportConfig(): StepFilterRule[];
|
|
77
|
+
/**
|
|
78
|
+
* Import filter configuration
|
|
79
|
+
*/
|
|
80
|
+
importConfig(rules: Array<Omit<StepFilterRule, 'id'>>): void;
|
|
81
|
+
}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Step Filter
|
|
3
|
+
* Manages step filtering to skip vendor/library code during debugging.
|
|
4
|
+
*/
|
|
5
|
+
import { logger } from '../utils/logger.js';
|
|
6
|
+
export class StepFilter {
|
|
7
|
+
rules = new Map();
|
|
8
|
+
ruleIdCounter = 0;
|
|
9
|
+
functionHistory = [];
|
|
10
|
+
maxHistorySize = 1000;
|
|
11
|
+
constructor() {
|
|
12
|
+
// Add default rules for common vendor directories
|
|
13
|
+
this.addRule('/vendor/', 'exclude', 'Skip Composer vendor directory');
|
|
14
|
+
this.addRule('/node_modules/', 'exclude', 'Skip Node modules');
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Add a step filter rule
|
|
18
|
+
*/
|
|
19
|
+
addRule(pattern, type, description) {
|
|
20
|
+
const id = `filter_${++this.ruleIdCounter}`;
|
|
21
|
+
const rule = {
|
|
22
|
+
id,
|
|
23
|
+
pattern,
|
|
24
|
+
type,
|
|
25
|
+
enabled: true,
|
|
26
|
+
description,
|
|
27
|
+
};
|
|
28
|
+
this.rules.set(id, rule);
|
|
29
|
+
logger.debug(`Step filter rule added: ${id} - ${type} ${pattern}`);
|
|
30
|
+
return rule;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Remove a rule
|
|
34
|
+
*/
|
|
35
|
+
removeRule(id) {
|
|
36
|
+
return this.rules.delete(id);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Enable/disable a rule
|
|
40
|
+
*/
|
|
41
|
+
setRuleEnabled(id, enabled) {
|
|
42
|
+
const rule = this.rules.get(id);
|
|
43
|
+
if (rule) {
|
|
44
|
+
rule.enabled = enabled;
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Get all rules
|
|
51
|
+
*/
|
|
52
|
+
getAllRules() {
|
|
53
|
+
return Array.from(this.rules.values());
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Check if a file should be skipped during stepping
|
|
57
|
+
*/
|
|
58
|
+
shouldSkip(filePath) {
|
|
59
|
+
const enabledRules = Array.from(this.rules.values()).filter((r) => r.enabled);
|
|
60
|
+
// Check exclude rules first
|
|
61
|
+
for (const rule of enabledRules) {
|
|
62
|
+
if (rule.type === 'exclude' && this.matchesPattern(filePath, rule.pattern)) {
|
|
63
|
+
// Check if any include rule overrides
|
|
64
|
+
const hasIncludeOverride = enabledRules.some((r) => r.type === 'include' && this.matchesPattern(filePath, r.pattern));
|
|
65
|
+
if (!hasIncludeOverride) {
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Check if a path matches a pattern
|
|
74
|
+
*/
|
|
75
|
+
matchesPattern(path, pattern) {
|
|
76
|
+
// Simple substring matching
|
|
77
|
+
if (pattern.startsWith('/') && pattern.endsWith('/')) {
|
|
78
|
+
// It's a regex pattern
|
|
79
|
+
try {
|
|
80
|
+
const regex = new RegExp(pattern.slice(1, -1));
|
|
81
|
+
return regex.test(path);
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
return path.includes(pattern);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
// Glob-like matching
|
|
88
|
+
if (pattern.includes('*')) {
|
|
89
|
+
const regexPattern = pattern
|
|
90
|
+
.replace(/[.+^${}()|[\]\\]/g, '\\$&')
|
|
91
|
+
.replace(/\*/g, '.*')
|
|
92
|
+
.replace(/\?/g, '.');
|
|
93
|
+
return new RegExp(regexPattern).test(path);
|
|
94
|
+
}
|
|
95
|
+
// Simple substring match
|
|
96
|
+
return path.includes(pattern);
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Record a function call in history
|
|
100
|
+
*/
|
|
101
|
+
recordFunctionCall(entry) {
|
|
102
|
+
this.functionHistory.push({
|
|
103
|
+
...entry,
|
|
104
|
+
timestamp: new Date(),
|
|
105
|
+
});
|
|
106
|
+
// Trim history if too large
|
|
107
|
+
if (this.functionHistory.length > this.maxHistorySize) {
|
|
108
|
+
this.functionHistory = this.functionHistory.slice(-this.maxHistorySize);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Get function call history
|
|
113
|
+
*/
|
|
114
|
+
getFunctionHistory(limit) {
|
|
115
|
+
if (limit) {
|
|
116
|
+
return this.functionHistory.slice(-limit);
|
|
117
|
+
}
|
|
118
|
+
return [...this.functionHistory];
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Clear function history
|
|
122
|
+
*/
|
|
123
|
+
clearHistory() {
|
|
124
|
+
this.functionHistory = [];
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Search function history
|
|
128
|
+
*/
|
|
129
|
+
searchHistory(query) {
|
|
130
|
+
const lowerQuery = query.toLowerCase();
|
|
131
|
+
return this.functionHistory.filter((entry) => entry.name.toLowerCase().includes(lowerQuery) ||
|
|
132
|
+
entry.file.toLowerCase().includes(lowerQuery));
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Get function call statistics
|
|
136
|
+
*/
|
|
137
|
+
getCallStatistics() {
|
|
138
|
+
const stats = new Map();
|
|
139
|
+
for (const entry of this.functionHistory) {
|
|
140
|
+
const existing = stats.get(entry.name);
|
|
141
|
+
if (existing) {
|
|
142
|
+
existing.count++;
|
|
143
|
+
if (entry.timestamp > existing.lastCall) {
|
|
144
|
+
existing.lastCall = entry.timestamp;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
stats.set(entry.name, { count: 1, lastCall: entry.timestamp });
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return stats;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Export filter configuration
|
|
155
|
+
*/
|
|
156
|
+
exportConfig() {
|
|
157
|
+
return this.getAllRules();
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Import filter configuration
|
|
161
|
+
*/
|
|
162
|
+
importConfig(rules) {
|
|
163
|
+
this.rules.clear();
|
|
164
|
+
this.ruleIdCounter = 0;
|
|
165
|
+
for (const rule of rules) {
|
|
166
|
+
this.addRule(rule.pattern, rule.type, rule.description);
|
|
167
|
+
const added = this.rules.get(`filter_${this.ruleIdCounter}`);
|
|
168
|
+
if (added) {
|
|
169
|
+
added.enabled = rule.enabled;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
//# sourceMappingURL=step-filter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"step-filter.js","sourceRoot":"","sources":["../../src/session/step-filter.ts"],"names":[],"mappings":"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"}
|