1111// SPDX-License-Identifier: Apache-2.0
1212//
1313//===----------------------------------------------------------------------===//
14+ import { DebugProtocol } from "@vscode/debugprotocol" ;
1415import * as vscode from "vscode" ;
1516
1617import { SwiftLogger } from "../logging/SwiftLogger" ;
@@ -72,6 +73,7 @@ export class LoggingDebugAdapterTracker implements vscode.DebugAdapterTracker {
7273 private exitHandler ?: ( exitCode : number ) => void ;
7374 private output : string [ ] = [ ] ;
7475 private exitCode : number | undefined ;
76+ private logger ?: SwiftLogger ;
7577
7678 constructor ( public id : string ) {
7779 LoggingDebugAdapterTracker . debugSessionIdMap [ id ] = this ;
@@ -90,6 +92,7 @@ export class LoggingDebugAdapterTracker implements vscode.DebugAdapterTracker {
9092 cb ( o ) ;
9193 }
9294 if ( loggingDebugAdapter . exitCode ) {
95+ loggingDebugAdapter . logger = logger ;
9396 exitHandler ( loggingDebugAdapter . exitCode ) ;
9497 }
9598 loggingDebugAdapter . output = [ ] ;
@@ -114,7 +117,7 @@ export class LoggingDebugAdapterTracker implements vscode.DebugAdapterTracker {
114117 return ;
115118 }
116119
117- this . handleBreakpointFallback ( debugMessage ) ;
120+ this . handleBreakpointEvent ( debugMessage ) ;
118121
119122 if ( debugMessage . event === "exited" && debugMessage . body . exitCode ) {
120123 this . exitCode = debugMessage . body . exitCode ;
@@ -134,27 +137,50 @@ export class LoggingDebugAdapterTracker implements vscode.DebugAdapterTracker {
134137 }
135138
136139 private handleBreakpointEvent ( rawMsg : unknown ) : void {
137- try {
138- // Minimal typed view of the event payload we care about.
139- type FrameLike = { source ?: { path ?: string } ; line ?: number } ;
140- type BodyLike = {
141- exitCode ?: number ;
142- category ?: string ;
143- output ?: string ;
144- reason ?: string ;
145- thread ?: { frames ?: FrameLike [ ] } ;
146- source ?: { path ?: string } ;
147- line ?: number ;
140+ // Narrow-bodied shapes for just the fields we use (local to this function).
141+ type StoppedBodyLike = {
142+ reason ?: string ;
143+ thread ?: {
144+ frames ?: {
145+ source ?: { path ?: string } ;
146+ line ?: number ;
147+ } [ ] ;
148148 } ;
149+ } ;
150+
151+ type BreakpointBodyLike = {
152+ source ?: { path ?: string } ;
153+ line ?: number ;
154+ } ;
155+
156+ try {
157+ const msg = rawMsg as DebugProtocol . ProtocolMessage ;
158+ const eventMsg = msg as DebugProtocol . Event ;
149159
150- const msg = rawMsg as { type ?: string ; event ?: string ; body ?: BodyLike | undefined } ;
151160 if ( ! msg || msg . type !== "event" ) {
152161 return ;
153162 }
154163
164+ const normalizePath = ( p : string ) : string => {
165+ try {
166+ // If adapter sends a URI-like path, parse it
167+ if ( p . startsWith ( "file://" ) || p . includes ( "://" ) ) {
168+ return vscode . Uri . parse ( p ) . fsPath ;
169+ }
170+ // Otherwise treat as filesystem path
171+ return vscode . Uri . file ( p ) . fsPath ;
172+ } catch {
173+ // Fallback: return raw
174+ return p ;
175+ }
176+ } ;
177+
155178 // Case A: stopped event with reason = "breakpoint"
156- if ( msg . event === "stopped" && msg . body ?. reason === "breakpoint" ) {
157- const frames = msg . body . thread ?. frames ;
179+ if (
180+ eventMsg . event === "stopped" &&
181+ ( eventMsg . body as StoppedBodyLike ) ?. reason === "breakpoint"
182+ ) {
183+ const frames = ( eventMsg . body as StoppedBodyLike ) ?. thread ?. frames ;
158184 if ( ! Array . isArray ( frames ) || frames . length === 0 ) {
159185 return ;
160186 }
@@ -169,15 +195,15 @@ export class LoggingDebugAdapterTracker implements vscode.DebugAdapterTracker {
169195 const bpLine0 = line - 1 ; // VS Code uses 0-based lines
170196
171197 const breakpoints = vscode . debug . breakpoints . filter (
172- b => b instanceof vscode . SourceBreakpoint
198+ b => ! ! ( b as vscode . SourceBreakpoint ) . location
173199 ) as vscode . SourceBreakpoint [ ] ;
174200
175201 for ( const bp of breakpoints ) {
176202 const loc = bp . location ;
177203 if ( ! loc ) {
178204 continue ;
179205 }
180- if ( loc . uri . fsPath !== sourcePath ) {
206+ if ( loc . uri . fsPath !== normalizePath ( sourcePath ) ) {
181207 continue ;
182208 }
183209 if ( loc . range . start . line !== bpLine0 ) {
@@ -193,9 +219,10 @@ export class LoggingDebugAdapterTracker implements vscode.DebugAdapterTracker {
193219 }
194220
195221 // Case B: explicit "breakpoint" event that carries source+line info
196- if ( msg . event === "breakpoint" && msg . body ) {
197- const sourcePath = msg . body . source ?. path ;
198- const line = msg . body . line ;
222+ if ( eventMsg . event === "breakpoint" && eventMsg . body ) {
223+ const body = eventMsg . body as BreakpointBodyLike ;
224+ const sourcePath = body . source ?. path ;
225+ const line = body . line ;
199226 if ( ! sourcePath || typeof line !== "number" ) {
200227 return ;
201228 }
@@ -210,7 +237,7 @@ export class LoggingDebugAdapterTracker implements vscode.DebugAdapterTracker {
210237 if ( ! loc ) {
211238 continue ;
212239 }
213- if ( loc . uri . fsPath !== sourcePath ) {
240+ if ( loc . uri . fsPath !== normalizePath ( sourcePath ) ) {
214241 continue ;
215242 }
216243 if ( loc . range . start . line !== bpLine0 ) {
@@ -225,7 +252,7 @@ export class LoggingDebugAdapterTracker implements vscode.DebugAdapterTracker {
225252 }
226253 } catch ( err ) {
227254 // eslint-disable-next-line no-console
228- console . error ( " Breakpoint fallback error:" , err ) ;
255+ this . logger ?. error ( ` Breakpoint fallback error: ${ String ( err ) } ` ) ;
229256 }
230257 }
231258
0 commit comments