@@ -264,38 +264,62 @@ export class ObjectScriptDebugSession extends LoggingDebugSession {
264264 } ) ;
265265
266266 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+ }
267274 xdebugBreakpoints = await Promise . all (
268275 args . breakpoints . map ( async ( breakpoint ) => {
269276 const line = breakpoint . line ;
270277 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
278302 if ( breakpoint . condition ) {
279303 return new xdebug . ClassConditionalBreakpoint (
280304 breakpoint . condition ,
281305 fileUri ,
282306 line ,
283- methodName ,
284- line - i - 2 ,
307+ currentSymbol . name ,
308+ line - methodlinenum - 1 ,
285309 breakpoint . hitCondition
286310 ) ;
287311 } else {
288312 return new xdebug . ClassLineBreakpoint (
289313 fileUri ,
290314 line ,
291- methodName ,
292- line - i - 2 ,
315+ currentSymbol . name ,
316+ line - methodlinenum - 1 ,
293317 breakpoint . hitCondition
294318 ) ;
295319 }
296320 }
297321 }
298- } ) ;
322+ }
299323 } else if ( filePath . endsWith ( "mac" ) || filePath . endsWith ( "int" ) ) {
300324 if ( breakpoint . condition ) {
301325 return new xdebug . RoutineConditionalBreakpoint (
@@ -450,25 +474,45 @@ export class ObjectScriptDebugSession extends LoggingDebugSession {
450474 const [ , namespace , name ] = decodeURI ( stackFrame . fileUri ) . match ( / ^ d b g p : \/ \/ \| ( [ ^ | ] + ) \| ( .* ) $ / ) ;
451475 const routine = name ;
452476 // 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 ( ) ) ;
455479 let line = stackFrame . line + 1 ;
456480 const place = `${ stackFrame . method } +${ stackFrame . methodOffset } ` ;
457481 const stackFrameId = this . _stackFrameIdCounter ++ ;
458482 let noSource = false ;
459483 try {
460- const document = await vscode . workspace . openTextDocument ( vscode . Uri . parse ( source . path ) ) ;
461484 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 ;
469497 break ;
470498 }
471499 }
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+ }
472516 }
473517 this . _stackFrames . set ( stackFrameId , stackFrame ) ;
474518 } catch ( ex ) {
0 commit comments