@@ -58,7 +58,7 @@ export interface AttachRequestArguments extends DebugProtocol.AttachRequestArgum
5858 additional_options : string ;
5959}
6060
61- export let pinnedScene : Uri ;
61+ export let pinnedScene : Uri | undefined ;
6262
6363class GDFileDecorationProvider implements FileDecorationProvider {
6464 private emitter = new EventEmitter < Uri > ( ) ;
@@ -70,7 +70,7 @@ class GDFileDecorationProvider implements FileDecorationProvider {
7070
7171 provideFileDecoration ( uri : Uri , token : CancellationToken ) : FileDecoration | undefined {
7272 if ( uri . scheme !== "file" ) return undefined ;
73- if ( pinnedScene && uri . fsPath === pinnedScene . fsPath ) {
73+ if ( pinnedScene !== undefined && uri . fsPath === pinnedScene . fsPath ) {
7474 return {
7575 badge : "🖈" ,
7676 } ;
@@ -100,8 +100,8 @@ export class GodotDebugger implements DebugAdapterDescriptorFactory, DebugConfig
100100 register_command ( "debugger.editValue" , this . edit_value . bind ( this ) ) ,
101101 register_command ( "debugger.debugCurrentFile" , this . debug_current_file . bind ( this ) ) ,
102102 register_command ( "debugger.debugPinnedFile" , this . debug_pinned_file . bind ( this ) ) ,
103- register_command ( "debugger.pinFile" , this . pin_file . bind ( this ) ) ,
104- register_command ( "debugger.unpinFile" , this . unpin_file . bind ( this ) ) ,
103+ register_command ( "debugger.pinFile" , this . pinFile . bind ( this ) ) ,
104+ register_command ( "debugger.unpinFile" , this . unpinFile . bind ( this ) ) ,
105105 register_command ( "debugger.openPinnedFile" , this . open_pinned_file . bind ( this ) ) ,
106106 this . inspector . view ,
107107 this . sceneTree . view ,
@@ -113,7 +113,7 @@ export class GodotDebugger implements DebugAdapterDescriptorFactory, DebugConfig
113113 const projectVersion = await get_project_version ( ) ;
114114 log . info ( `Project version identified as ${ projectVersion } ` ) ;
115115
116- if ( projectVersion . startsWith ( "4" ) ) {
116+ if ( projectVersion ? .startsWith ( "4" ) ) {
117117 this . session = new Godot4DebugSession ( projectVersion ) ;
118118 } else {
119119 this . session = new Godot3DebugSession ( ) ;
@@ -168,13 +168,13 @@ export class GodotDebugger implements DebugAdapterDescriptorFactory, DebugConfig
168168 public debug_current_file ( ) {
169169 log . info ( "Attempting to debug current file" ) ;
170170 const configs : DebugConfiguration [ ] = workspace
171- . getConfiguration ( "launch" , window . activeTextEditor . document . uri )
172- . get ( "configurations" ) ;
171+ . getConfiguration ( "launch" , window . activeTextEditor ? .document . uri )
172+ . get ( "configurations" ) || [ ] ;
173173 const launches = configs . filter ( ( c ) => c . request === "launch" ) ;
174174 const currents = configs . filter ( ( c ) => c . scene === "current" ) ;
175175
176- let path = window . activeTextEditor . document . fileName ;
177- if ( path . endsWith ( ".gd" ) ) {
176+ let path = window . activeTextEditor ? .document . fileName ;
177+ if ( path ? .endsWith ( ".gd" ) ) {
178178 const scenePath = path . replace ( ".gd" , ".tscn" ) ;
179179 if ( ! fs . existsSync ( scenePath ) ) {
180180 const message = `Can't launch debug session: no associated scene for '${ path } '. (Script and scene file must have the same name.)` ;
@@ -196,12 +196,12 @@ export class GodotDebugger implements DebugAdapterDescriptorFactory, DebugConfig
196196 config . scene = path ;
197197
198198 log . info ( `Starting debug session for '${ path } '` ) ;
199- debug . startDebugging ( workspace . workspaceFolders [ 0 ] , config ) ;
199+ debug . startDebugging ( workspace . workspaceFolders ?. [ 0 ] , config ) ;
200200 }
201201
202202 public debug_pinned_file ( ) {
203203 log . info ( "Attempting to debug pinned scene" ) ;
204- const configs : DebugConfiguration [ ] = workspace . getConfiguration ( "launch" , pinnedScene ) . get ( "configurations" ) ;
204+ const configs : DebugConfiguration [ ] = workspace . getConfiguration ( "launch" , pinnedScene ) . get ( "configurations" ) || [ ] ;
205205 const launches = configs . filter ( ( c ) => c . request === "launch" ) ;
206206 const currents = configs . filter ( ( c ) => c . scene === "pinned" ) ;
207207
@@ -231,13 +231,17 @@ export class GodotDebugger implements DebugAdapterDescriptorFactory, DebugConfig
231231 config . scene = path ;
232232
233233 log . info ( `Starting debug session for '${ path } '` ) ;
234- debug . startDebugging ( workspace . workspaceFolders [ 0 ] , config ) ;
234+ debug . startDebugging ( workspace . workspaceFolders ?. [ 0 ] , config ) ;
235235 }
236236
237- public pin_file ( uri : Uri ) {
237+ public pinFile ( uri : Uri | undefined ) {
238238 let _uri = uri ;
239239 if ( uri === undefined ) {
240- _uri = window . activeTextEditor . document . uri ;
240+ _uri = window . activeTextEditor ?. document . uri ;
241+ }
242+ if ( _uri === undefined ) {
243+ window . showWarningMessage ( "No active editor. Open a file to pin it." ) ;
244+ return ;
241245 }
242246 log . info ( `Pinning debug target file: '${ _uri . fsPath } '` ) ;
243247 set_context ( "pinnedScene" , [ _uri . fsPath ] ) ;
@@ -249,17 +253,19 @@ export class GodotDebugger implements DebugAdapterDescriptorFactory, DebugConfig
249253 this . fileDecorations . update ( _uri ) ;
250254 }
251255
252- public unpin_file ( uri : Uri ) {
256+ public unpinFile ( uri : Uri ) {
253257 log . info ( `Unpinning debug target file: '${ pinnedScene } '` ) ;
254258 set_context ( "pinnedScene" , [ ] ) ;
255259 const previousPinnedScene = pinnedScene ;
256260 pinnedScene = undefined ;
257261 this . context . workspaceState . update ( "pinnedScene" , pinnedScene ) ;
258- this . fileDecorations . update ( previousPinnedScene ) ;
262+ if ( previousPinnedScene ) {
263+ this . fileDecorations . update ( previousPinnedScene ) ;
264+ }
259265 }
260266
261267 public restore_pinned_file ( ) {
262- pinnedScene = this . context . workspaceState . get ( "pinnedScene" , undefined ) ;
268+ pinnedScene = this . context . workspaceState . get < Uri > ( "pinnedScene" ) ;
263269 if ( pinnedScene ) {
264270 log . info ( `Restoring pinned debug target file: '${ pinnedScene . fsPath } '` ) ;
265271 set_context ( "pinnedScene" , [ pinnedScene . fsPath ] ) ;
@@ -278,6 +284,10 @@ export class GodotDebugger implements DebugAdapterDescriptorFactory, DebugConfig
278284 }
279285
280286 private async fill_inspector ( element : SceneNode | RemoteProperty , force_refresh = false ) {
287+ if ( element . object_id === undefined ) {
288+ return ;
289+ }
290+
281291 if ( this . session instanceof Godot4DebugSession ) {
282292 const godot_object = await this . session . variables_manager ?. get_godot_object (
283293 BigInt ( element . object_id ) ,
@@ -313,11 +323,17 @@ export class GodotDebugger implements DebugAdapterDescriptorFactory, DebugConfig
313323 public async refresh_inspector ( ) {
314324 if ( this . inspector . has_tree ( ) ) {
315325 const item = this . inspector . get_top_item ( ) ;
316- await this . fill_inspector ( item , /*force_refresh*/ true ) ;
326+ if ( item ) {
327+ await this . fill_inspector ( item , /*force_refresh*/ true ) ;
328+ }
317329 }
318330 }
319331
320332 public async edit_value ( property : RemoteProperty ) {
333+ if ( property . object_id === undefined ) {
334+ log . error ( "Invalid property to edit (property.object_id === undefined)" ) ;
335+ return ;
336+ }
321337 const previous_value = property . value ;
322338 const type = typeof previous_value ;
323339 const is_float = type === "number" && ! Number . isInteger ( previous_value ) ;
@@ -328,6 +344,9 @@ export class GodotDebugger implements DebugAdapterDescriptorFactory, DebugConfig
328344 new_parsed_value = value ;
329345 break ;
330346 case "number" :
347+ if ( ! value ) {
348+ return ;
349+ }
331350 if ( is_float ) {
332351 new_parsed_value = Number . parseFloat ( value ) ;
333352 if ( Number . isNaN ( new_parsed_value ) ) {
@@ -341,19 +360,26 @@ export class GodotDebugger implements DebugAdapterDescriptorFactory, DebugConfig
341360 }
342361 break ;
343362 case "boolean" :
363+ if ( ! value ) {
364+ return ;
365+ }
344366 if ( value . toLowerCase ( ) === "true" || value . toLowerCase ( ) === "false" ) {
345367 new_parsed_value = value . toLowerCase ( ) === "true" ;
346368 } else if ( value === "0" || value === "1" ) {
347369 new_parsed_value = value === "1" ;
348370 } else {
349371 return ;
350372 }
373+ break ;
351374 }
352- if ( property . changes_parent ) {
375+ if ( property . changes_parent && property . parent !== undefined ) {
353376 const parents = [ property . parent ] ;
354377 let idx = 0 ;
355378 while ( parents [ idx ] . changes_parent ) {
356- parents . push ( parents [ idx ++ ] . parent ) ;
379+ const parent = parents [ idx ++ ] . parent ;
380+ if ( parent ) {
381+ parents . push ( parent ) ;
382+ }
357383 }
358384 const changed_value = this . inspector . get_changed_value ( parents , property , new_parsed_value ) ;
359385 this . session ?. controller . set_object_property ( BigInt ( property . object_id ) , parents [ idx ] . label , changed_value ) ;
@@ -362,9 +388,11 @@ export class GodotDebugger implements DebugAdapterDescriptorFactory, DebugConfig
362388 }
363389
364390 const item = this . inspector . get_top_item ( ) ;
365- await this . fill_inspector ( item , /*force_refresh*/ true ) ;
391+ if ( item ) {
392+ await this . fill_inspector ( item , /*force_refresh*/ true ) ;
393+ }
366394
367395 // const res = await debug.activeDebugSession?.customRequest("refreshVariables"); // refresh vscode.debug variables
368- this . session . sendEvent ( new InvalidatedEvent ( [ "variables" ] ) ) ;
396+ this . session ? .sendEvent ( new InvalidatedEvent ( [ "variables" ] ) ) ;
369397 }
370398}
0 commit comments