@@ -264,38 +264,62 @@ export class ObjectScriptDebugSession extends LoggingDebugSession {
264
264
} ) ;
265
265
266
266
let xdebugBreakpoints : ( xdebug . ConditionalBreakpoint | xdebug . ClassLineBreakpoint | xdebug . LineBreakpoint ) [ ] = [ ] ;
267
+ let symbols : vscode . DocumentSymbol [ ] ;
268
+ if ( fileName . endsWith ( "cls" ) ) {
269
+ // Compute DocumentSymbols for this class
270
+ symbols = (
271
+ await vscode . commands . executeCommand < vscode . DocumentSymbol [ ] > ( "vscode.executeDocumentSymbolProvider" , uri )
272
+ ) [ 0 ] . children ;
273
+ }
267
274
xdebugBreakpoints = await Promise . all (
268
275
args . breakpoints . map ( async ( breakpoint ) => {
269
276
const line = breakpoint . line ;
270
277
if ( fileName . endsWith ( "cls" ) ) {
271
- return await vscode . workspace . openTextDocument ( uri ) . then ( ( document ) => {
272
- const methodMatchPattern = new RegExp ( `^(?:Class)?Method ([^(]+)(?=[( ])` , "i" ) ;
273
- for ( let i = line ; line > 0 ; i -- ) {
274
- const lineOfCode = document . lineAt ( i ) . text ;
275
- const methodMatch = lineOfCode . match ( methodMatchPattern ) ;
276
- if ( methodMatch ) {
277
- const [ , methodName ] = methodMatch ;
278
+ // Find the class member that this breakpoint is in
279
+ let currentSymbol : vscode . DocumentSymbol ;
280
+ for ( const symbol of symbols ) {
281
+ if ( symbol . range . contains ( new vscode . Position ( line , 0 ) ) ) {
282
+ currentSymbol = symbol ;
283
+ break ;
284
+ }
285
+ }
286
+ if (
287
+ currentSymbol !== undefined &&
288
+ currentSymbol . kind === vscode . SymbolKind . Method &&
289
+ currentSymbol . detail . toLowerCase ( ) !== "query"
290
+ ) {
291
+ // This breakpoint is in a method
292
+ const currentdoc = await vscode . workspace . openTextDocument ( uri ) ;
293
+ for (
294
+ let methodlinenum = currentSymbol . selectionRange . start . line ;
295
+ methodlinenum <= currentSymbol . range . end . line ;
296
+ methodlinenum ++
297
+ ) {
298
+ // Find the offset of this breakpoint in the method
299
+ const methodlinetext : string = currentdoc . lineAt ( methodlinenum ) . text . trim ( ) ;
300
+ if ( methodlinetext . endsWith ( "{" ) ) {
301
+ // This is the last line of the method definition, so count from here
278
302
if ( breakpoint . condition ) {
279
303
return new xdebug . ClassConditionalBreakpoint (
280
304
breakpoint . condition ,
281
305
fileUri ,
282
306
line ,
283
- methodName ,
284
- line - i - 2 ,
307
+ currentSymbol . name ,
308
+ line - methodlinenum - 1 ,
285
309
breakpoint . hitCondition
286
310
) ;
287
311
} else {
288
312
return new xdebug . ClassLineBreakpoint (
289
313
fileUri ,
290
314
line ,
291
- methodName ,
292
- line - i - 2 ,
315
+ currentSymbol . name ,
316
+ line - methodlinenum - 1 ,
293
317
breakpoint . hitCondition
294
318
) ;
295
319
}
296
320
}
297
321
}
298
- } ) ;
322
+ }
299
323
} else if ( filePath . endsWith ( "mac" ) || filePath . endsWith ( "int" ) ) {
300
324
if ( breakpoint . condition ) {
301
325
return new xdebug . RoutineConditionalBreakpoint (
@@ -450,25 +474,45 @@ export class ObjectScriptDebugSession extends LoggingDebugSession {
450
474
const [ , namespace , name ] = decodeURI ( stackFrame . fileUri ) . match ( / ^ d b g p : \/ \/ \| ( [ ^ | ] + ) \| ( .* ) $ / ) ;
451
475
const routine = name ;
452
476
// const routine = name.includes(".") ? name : name + ".int";
453
- const fileUri = DocumentContentProvider . getUri ( routine , this . _workspace , namespace ) . toString ( ) ;
454
- const source = new Source ( routine , fileUri ) ;
477
+ const fileUri = DocumentContentProvider . getUri ( routine , this . _workspace , namespace ) ;
478
+ const source = new Source ( routine , fileUri . toString ( ) ) ;
455
479
let line = stackFrame . line + 1 ;
456
480
const place = `${ stackFrame . method } +${ stackFrame . methodOffset } ` ;
457
481
const stackFrameId = this . _stackFrameIdCounter ++ ;
458
482
let noSource = false ;
459
483
try {
460
- const document = await vscode . workspace . openTextDocument ( vscode . Uri . parse ( source . path ) ) ;
461
484
if ( source . name . endsWith ( ".cls" ) && stackFrame . method !== "" ) {
462
- const methodMatchPattern = new RegExp ( `^(Class)?Method ${ stackFrame . method } (?=[( ])` , "i" ) ;
463
- for ( let i = 0 ; i < document . lineCount ; i ++ ) {
464
- const codeLine = document . lineAt ( i ) ;
465
-
466
- const methodMatch = codeLine . text . match ( methodMatchPattern ) ;
467
- if ( methodMatch ) {
468
- line = i + 2 + stackFrame . methodOffset ;
485
+ // Compute DocumentSymbols for this class
486
+ const symbols : vscode . DocumentSymbol [ ] = (
487
+ await vscode . commands . executeCommand < vscode . DocumentSymbol [ ] > (
488
+ "vscode.executeDocumentSymbolProvider" ,
489
+ fileUri
490
+ )
491
+ ) [ 0 ] . children ;
492
+ // Find the DocumentSymbol for this method
493
+ let currentSymbol : vscode . DocumentSymbol ;
494
+ for ( const symbol of symbols ) {
495
+ if ( symbol . name === stackFrame . method && symbol . detail . toLowerCase ( ) . includes ( "method" ) ) {
496
+ currentSymbol = symbol ;
469
497
break ;
470
498
}
471
499
}
500
+ if ( currentSymbol !== undefined ) {
501
+ const currentdoc = await vscode . workspace . openTextDocument ( fileUri ) ;
502
+ for (
503
+ let methodlinenum = currentSymbol . selectionRange . start . line ;
504
+ methodlinenum <= currentSymbol . range . end . line ;
505
+ methodlinenum ++
506
+ ) {
507
+ // Find the offset of this breakpoint in the method
508
+ const methodlinetext : string = currentdoc . lineAt ( methodlinenum ) . text . trim ( ) ;
509
+ if ( methodlinetext . endsWith ( "{" ) ) {
510
+ // This is the last line of the method definition, so count from here
511
+ line = methodlinenum + stackFrame . methodOffset + 1 ;
512
+ break ;
513
+ }
514
+ }
515
+ }
472
516
}
473
517
this . _stackFrames . set ( stackFrameId , stackFrame ) ;
474
518
} catch ( ex ) {
0 commit comments