11import * as child_process from "node:child_process" ;
2+ import * as path from "path" ;
23import { isDeepStrictEqual } from "util" ;
34import * as vscode from "vscode" ;
45
@@ -12,6 +13,10 @@ export class LLDBDapServer implements vscode.Disposable {
1213 private serverProcess ?: child_process . ChildProcessWithoutNullStreams ;
1314 private serverInfo ?: Promise < { host : string ; port : number } > ;
1415 private serverSpawnInfo ?: string [ ] ;
16+ // Detects changes to the lldb-dap executable file since the server's startup.
17+ private serverFileWatcher ?: vscode . FileSystemWatcher ;
18+ // Indicates whether the lldb-dap executable file has changed since the server's startup.
19+ private serverFileChanged ?: boolean ;
1520
1621 constructor ( ) {
1722 vscode . commands . registerCommand (
@@ -83,6 +88,18 @@ export class LLDBDapServer implements vscode.Disposable {
8388 } ) ;
8489 this . serverProcess = process ;
8590 this . serverSpawnInfo = this . getSpawnInfo ( dapPath , dapArgs , options ?. env ) ;
91+ this . serverFileChanged = false ;
92+ // Cannot do `createFileSystemWatcher(dapPath)` for a single file. Have to use `RelativePattern`.
93+ // See https://github.com/microsoft/vscode/issues/141011#issuecomment-1016772527
94+ this . serverFileWatcher = vscode . workspace . createFileSystemWatcher (
95+ new vscode . RelativePattern (
96+ vscode . Uri . file ( path . dirname ( dapPath ) ) ,
97+ path . basename ( dapPath ) ,
98+ ) ,
99+ ) ;
100+ this . serverFileWatcher . onDidChange ( ( ) => {
101+ this . serverFileChanged = true ;
102+ } ) ;
86103 } ) ;
87104 return this . serverInfo ;
88105 }
@@ -100,20 +117,34 @@ export class LLDBDapServer implements vscode.Disposable {
100117 args : string [ ] ,
101118 env : NodeJS . ProcessEnv | { [ key : string ] : string } | undefined ,
102119 ) : Promise < boolean > {
103- if ( ! this . serverProcess || ! this . serverInfo || ! this . serverSpawnInfo ) {
120+ if (
121+ ! this . serverProcess ||
122+ ! this . serverInfo ||
123+ ! this . serverSpawnInfo ||
124+ ! this . serverFileWatcher ||
125+ this . serverFileChanged === undefined
126+ ) {
104127 return true ;
105128 }
106129
107- const newSpawnInfo = this . getSpawnInfo ( dapPath , args , env ) ;
108- if ( isDeepStrictEqual ( this . serverSpawnInfo , newSpawnInfo ) ) {
109- return true ;
110- }
130+ // Check if the server has changed. If so, generate message and detail for user prompt.
131+ const messageAndDetail = ( ( ) => {
132+ if ( this . serverFileChanged ) {
133+ return {
134+ message :
135+ "The lldb-dap binary has changed. Would you like to restart the server?" ,
136+ detail : `An existing lldb-dap server (${ this . serverProcess . pid } ) is running with an old binary.
111137
112- const userInput = await vscode . window . showInformationMessage (
113- "The arguments to lldb-dap have changed. Would you like to restart the server?" ,
114- {
115- modal : true ,
116- detail : `An existing lldb-dap server (${ this . serverProcess . pid } ) is running with different arguments.
138+ Restarting the server will interrupt any existing debug sessions and start a new server.` ,
139+ } ;
140+ }
141+
142+ const newSpawnInfo = this . getSpawnInfo ( dapPath , args , env ) ;
143+ if ( ! isDeepStrictEqual ( this . serverSpawnInfo , newSpawnInfo ) ) {
144+ return {
145+ message :
146+ "The arguments to lldb-dap have changed. Would you like to restart the server?" ,
147+ detail : `An existing lldb-dap server (${ this . serverProcess . pid } ) is running with different arguments.
117148
118149The previous lldb-dap server was started with:
119150
@@ -124,15 +155,31 @@ The new lldb-dap server will be started with:
124155${ newSpawnInfo . join ( " " ) }
125156
126157Restarting the server will interrupt any existing debug sessions and start a new server.` ,
158+ } ;
159+ }
160+
161+ return null ;
162+ } ) ( ) ;
163+
164+ // If the server hasn't changed, continue startup without killing it.
165+ if ( messageAndDetail === null ) {
166+ return true ;
167+ }
168+
169+ // The server has changed. Prompt the user to restart it.
170+ const { message, detail } = messageAndDetail ;
171+ const userInput = await vscode . window . showInformationMessage (
172+ message ,
173+ {
174+ modal : true ,
175+ detail,
127176 } ,
128177 "Restart" ,
129178 "Use Existing" ,
130179 ) ;
131180 switch ( userInput ) {
132181 case "Restart" :
133- this . serverProcess . kill ( ) ;
134- this . serverProcess = undefined ;
135- this . serverInfo = undefined ;
182+ this . dispose ( ) ;
136183 return true ;
137184 case "Use Existing" :
138185 return true ;
@@ -156,6 +203,10 @@ Restarting the server will interrupt any existing debug sessions and start a new
156203 if ( this . serverProcess === process ) {
157204 this . serverProcess = undefined ;
158205 this . serverInfo = undefined ;
206+ this . serverSpawnInfo = undefined ;
207+ this . serverFileWatcher ?. dispose ( ) ;
208+ this . serverFileWatcher = undefined ;
209+ this . serverFileChanged = undefined ;
159210 }
160211 }
161212
0 commit comments