@@ -14,6 +14,7 @@ import { IEditorServicesSessionDetails, SessionManager, SessionStatus } from "..
14
14
import Settings = require( "../settings" ) ;
15
15
import { Logger } from "../logging" ;
16
16
import { LanguageClientConsumer } from "../languageClientConsumer" ;
17
+ import path = require( "path" ) ;
17
18
18
19
export const StartDebuggerNotificationType =
19
20
new NotificationType < void > ( "powerShell/startDebugger" ) ;
@@ -121,7 +122,6 @@ export class DebugSessionFeature extends LanguageClientConsumer
121
122
type : "PowerShell" ,
122
123
request : "launch" ,
123
124
script : "${file}" ,
124
- cwd : "${file}" ,
125
125
} ,
126
126
] ;
127
127
case DebugConfig . LaunchScript :
@@ -130,8 +130,7 @@ export class DebugSessionFeature extends LanguageClientConsumer
130
130
name : "PowerShell: Launch Script" ,
131
131
type : "PowerShell" ,
132
132
request : "launch" ,
133
- script : "enter path or command to execute e.g.: ${workspaceFolder}/src/foo.ps1 or Invoke-Pester" ,
134
- cwd : "${workspaceFolder}" ,
133
+ script : "Enter path or command to execute, for example: \"${workspaceFolder}/src/foo.ps1\" or \"Invoke-Pester\"" ,
135
134
} ,
136
135
] ;
137
136
case DebugConfig . InteractiveSession :
@@ -140,7 +139,6 @@ export class DebugSessionFeature extends LanguageClientConsumer
140
139
name : "PowerShell: Interactive Session" ,
141
140
type : "PowerShell" ,
142
141
request : "launch" ,
143
- cwd : "" ,
144
142
} ,
145
143
] ;
146
144
case DebugConfig . AttachHostProcess :
@@ -155,168 +153,133 @@ export class DebugSessionFeature extends LanguageClientConsumer
155
153
}
156
154
}
157
155
158
- // DebugConfigurationProvider method
156
+ // DebugConfigurationProvider methods
159
157
public async resolveDebugConfiguration (
160
158
_folder : WorkspaceFolder | undefined ,
161
159
config : DebugConfiguration ,
162
160
_token ?: CancellationToken ) : Promise < DebugConfiguration > {
163
161
164
- if ( this . sessionManager . getSessionStatus ( ) !== SessionStatus . Running ) {
165
- await this . sessionManager . start ( ) ;
166
- }
162
+ // Prevent the Debug Console from opening
163
+ config . internalConsoleOptions = "neverOpen" ;
167
164
168
- // Starting a debug session can be done when there is no document open e.g. attach to PS host process
169
- const currentDocument = vscode . window . activeTextEditor ? vscode . window . activeTextEditor . document : undefined ;
170
- const debugCurrentScript = ( config . script === "${file}" ) || ! config . request ;
171
- const generateLaunchConfig = ! config . request ;
165
+ // NOTE: We intentionally do not touch the `cwd` setting of the config.
172
166
167
+ // If the createTemporaryIntegratedConsole field is not specified in the
168
+ // launch config, set the field using the value from the corresponding
169
+ // setting. Otherwise, the launch config value overrides the setting.
170
+ //
171
+ // Also start the temporary process and console for this configuration.
173
172
const settings = Settings . load ( ) ;
174
-
175
- // If the createTemporaryIntegratedConsole field is not specified in the launch config, set the field using
176
- // the value from the corresponding setting. Otherwise, the launch config value overrides the setting.
177
173
config . createTemporaryIntegratedConsole =
178
174
config . createTemporaryIntegratedConsole ??
179
175
settings . debugging . createTemporaryIntegratedConsole ;
180
176
181
- if ( config . request === "attach" ) {
182
- const platformDetails = getPlatformDetails ( ) ;
183
- const versionDetails = this . sessionManager . getPowerShellVersionDetails ( ) ;
184
-
185
- // Cross-platform attach to process was added in 6.2.0-preview.4
186
- if ( versionDetails . version < "6.2.0" && platformDetails . operatingSystem !== OperatingSystem . Windows ) {
187
- const msg = `Attaching to a PowerShell Host Process on ${
188
- OperatingSystem [ platformDetails . operatingSystem ] } requires PowerShell 6.2 or higher.`;
189
- return vscode . window . showErrorMessage ( msg ) . then ( ( _ ) => {
190
- return undefined ;
191
- } ) ;
192
- }
193
-
194
- // if nothing is set, prompt for the processId
195
- if ( ! config . customPipeName && ! config . processId ) {
196
- config . processId = await vscode . commands . executeCommand ( "PowerShell.PickPSHostProcess" ) ;
197
-
198
- // No process selected. Cancel attach.
199
- if ( ! config . processId ) {
200
- return null ;
201
- }
202
- }
203
-
204
- if ( ! config . runspaceId && ! config . runspaceName ) {
205
- config . runspaceId = await vscode . commands . executeCommand ( "PowerShell.PickRunspace" , config . processId ) ;
206
-
207
- // No runspace selected. Cancel attach.
208
- if ( ! config . runspaceId ) {
209
- return null ;
210
- }
211
- }
177
+ if ( config . createTemporaryIntegratedConsole ) {
178
+ this . tempDebugProcess = this . sessionManager . createDebugSessionProcess ( settings ) ;
179
+ this . tempSessionDetails = await this . tempDebugProcess . start ( `DebugSession-${ this . sessionCount ++ } ` ) ;
212
180
}
213
181
214
- // TODO: Use a named debug configuration.
215
- if ( generateLaunchConfig ) {
216
- // No launch.json, create the default configuration for both unsaved (Untitled) and saved documents.
182
+ if ( ! config . request ) {
183
+ // No launch.json, create the default configuration for both unsaved
184
+ // (Untitled) and saved documents.
185
+ config . current_document = true ;
217
186
config . type = "PowerShell" ;
218
187
config . name = "PowerShell: Launch Current File" ;
219
188
config . request = "launch" ;
220
189
config . args = [ ] ;
190
+ config . script = "${file}"
191
+ }
221
192
222
- config . script =
223
- currentDocument . isUntitled
224
- ? currentDocument . uri . toString ( )
225
- : currentDocument . fileName ;
226
-
227
- if ( config . createTemporaryIntegratedConsole ) {
228
- // For a folder-less workspace, vscode.workspace.rootPath will be undefined.
229
- // PSES will convert that undefined to a reasonable working dir.
230
- config . cwd =
231
- currentDocument . isUntitled
232
- ? vscode . workspace . rootPath
233
- : currentDocument . fileName ;
234
-
235
- } else {
236
- // If the non-temp Extension Terminal is being used, default to the current working dir.
237
- config . cwd = "" ;
193
+ if ( config . script === "${file}" || config . script === "${relativeFile}" ) {
194
+ if ( vscode . window . activeTextEditor === undefined ) {
195
+ vscode . window . showErrorMessage ( "To debug the 'Current File', you must first open a PowerShell script file in the editor." ) ;
196
+ return undefined ;
197
+ }
198
+ config . current_document = true ;
199
+ // Special case using the URI for untitled documents.
200
+ const currentDocument = vscode . window . activeTextEditor . document ;
201
+ if ( currentDocument . isUntitled ) {
202
+ config . untitled_document = true ;
203
+ config . script = currentDocument . uri . toString ( ) ;
238
204
}
239
205
}
240
206
241
- if ( config . request === "launch" ) {
242
- // For debug launch of "current script" (saved or unsaved), warn before starting the debugger if either
243
- // A) there is not an active document
244
- // B) the unsaved document's language type is not PowerShell
245
- // C) the saved document's extension is a type that PowerShell can't debug.
246
- if ( debugCurrentScript ) {
247
-
248
- if ( currentDocument === undefined ) {
249
- const msg = "To debug the \"Current File\", you must first open a " +
250
- "PowerShell script file in the editor." ;
251
- vscode . window . showErrorMessage ( msg ) ;
252
- return ;
253
- }
254
-
255
- if ( currentDocument . isUntitled ) {
256
- if ( config . createTemporaryIntegratedConsole ) {
257
- const msg = "Debugging Untitled files in a temporary console is currently not supported." ;
258
- vscode . window . showErrorMessage ( msg ) ;
259
- return ;
260
- }
261
-
262
- if ( currentDocument . languageId === "powershell" ) {
263
- if ( ! generateLaunchConfig ) {
264
- // Cover the case of existing launch.json but unsaved (Untitled) document.
265
- // In this case, vscode.workspace.rootPath will not be undefined.
266
- config . script = currentDocument . uri . toString ( ) ;
267
- config . cwd = vscode . workspace . rootPath ;
268
- }
269
- } else {
270
- const msg = "To debug '" + currentDocument . fileName + "', change the document's " +
271
- "language mode to PowerShell or save the file with a PowerShell extension." ;
272
- vscode . window . showErrorMessage ( msg ) ;
273
- return ;
274
- }
275
- } else {
276
- let isValidExtension = false ;
277
- const extIndex = currentDocument . fileName . lastIndexOf ( "." ) ;
278
- if ( extIndex !== - 1 ) {
279
- const ext = currentDocument . fileName . substr ( extIndex + 1 ) . toUpperCase ( ) ;
280
- isValidExtension = ( ext === "PS1" || ext === "PSM1" ) ;
281
- }
282
-
283
- if ( ( currentDocument . languageId !== "powershell" ) || ! isValidExtension ) {
284
- let docPath = currentDocument . fileName ;
285
- const workspaceRootPath = vscode . workspace . rootPath ;
286
- if ( currentDocument . fileName . startsWith ( workspaceRootPath ) ) {
287
- docPath = currentDocument . fileName . substring ( vscode . workspace . rootPath . length + 1 ) ;
288
- }
289
-
290
- const msg = "PowerShell does not support debugging this file type: '" + docPath + "'." ;
291
- vscode . window . showErrorMessage ( msg ) ;
292
- return ;
293
- }
207
+ return config ;
208
+ }
294
209
295
- if ( config . script === "${file}" ) {
296
- config . script = currentDocument . fileName ;
297
- }
298
- }
299
- }
210
+ public async resolveDebugConfigurationWithSubstitutedVariables (
211
+ _folder : WorkspaceFolder | undefined ,
212
+ config : DebugConfiguration ,
213
+ _token ?: CancellationToken ) : Promise < DebugConfiguration > {
300
214
301
- // NOTE: There is a tight coupling to a weird setting in
302
- // `package.json` for the Launch Current File configuration where
303
- // the default cwd is set to ${file}.
304
- if ( ( currentDocument !== undefined ) && ( config . cwd === "${file}" ) ) {
305
- config . cwd = currentDocument . fileName ;
306
- }
215
+ if ( config . request === "attach" ) {
216
+ config = await this . resolveAttachDebugConfiguration ( config ) ;
217
+ } else if ( config . request === "launch" ) {
218
+ config = await this . resolveLaunchDebugConfiguration ( config ) ;
219
+ } else {
220
+ vscode . window . showErrorMessage ( `The request type was invalid: '${ config . request } '` ) ;
221
+ return null ;
307
222
}
308
223
309
- // Prevent the Debug Console from opening
310
- config . internalConsoleOptions = "neverOpen" ;
311
-
312
- // Create or show the interactive console
224
+ // Start the PowerShell session if needed.
225
+ if ( this . sessionManager . getSessionStatus ( ) !== SessionStatus . Running ) {
226
+ await this . sessionManager . start ( ) ;
227
+ }
228
+ // Create or show the Extension Terminal.
313
229
vscode . commands . executeCommand ( "PowerShell.ShowSessionConsole" , true ) ;
314
230
315
- if ( config . createTemporaryIntegratedConsole ) {
316
- this . tempDebugProcess = this . sessionManager . createDebugSessionProcess ( settings ) ;
317
- this . tempSessionDetails = await this . tempDebugProcess . start ( `DebugSession-${ this . sessionCount ++ } ` ) ;
231
+ return config ;
232
+ }
233
+
234
+ private async resolveLaunchDebugConfiguration ( config : DebugConfiguration ) : Promise < DebugConfiguration > {
235
+ // Check the languageId only for current documents (which includes untitled documents).
236
+ if ( config . current_document ) {
237
+ const currentDocument = vscode . window . activeTextEditor . document ;
238
+ if ( currentDocument . languageId !== "powershell" ) {
239
+ vscode . window . showErrorMessage ( "Please change the current document's language mode to PowerShell." ) ;
240
+ return undefined ;
241
+ }
242
+ }
243
+ // Check the temporary console setting for untitled documents only, and
244
+ // check the document extension for everything else.
245
+ if ( config . untitled_document ) {
246
+ if ( config . createTemporaryIntegratedConsole ) {
247
+ vscode . window . showErrorMessage ( "Debugging untitled files in a temporary console is not supported." ) ;
248
+ return undefined ;
249
+ }
250
+ } else {
251
+ const ext = path . extname ( config . script ) . toLowerCase ( ) ;
252
+ if ( ! ( ext === ".ps1" || ext === ".psm1" ) ) {
253
+ vscode . window . showErrorMessage ( `PowerShell does not support debugging this file type: '${ path . basename ( config . script ) } '` ) ;
254
+ return undefined ;
255
+ }
318
256
}
257
+ return config ;
258
+ }
319
259
260
+ private async resolveAttachDebugConfiguration ( config : DebugConfiguration ) : Promise < DebugConfiguration > {
261
+ const platformDetails = getPlatformDetails ( ) ;
262
+ const versionDetails = this . sessionManager . getPowerShellVersionDetails ( ) ;
263
+ // Cross-platform attach to process was added in 6.2.0-preview.4.
264
+ if ( versionDetails . version < "7.0.0" && platformDetails . operatingSystem !== OperatingSystem . Windows ) {
265
+ vscode . window . showErrorMessage ( `Attaching to a PowerShell Host Process on ${ OperatingSystem [ platformDetails . operatingSystem ] } requires PowerShell 7.0 or higher.` ) ;
266
+ return undefined ;
267
+ }
268
+ // If nothing is set, prompt for the processId.
269
+ if ( ! config . customPipeName && ! config . processId ) {
270
+ config . processId = await vscode . commands . executeCommand ( "PowerShell.PickPSHostProcess" ) ;
271
+ // No process selected. Cancel attach.
272
+ if ( ! config . processId ) {
273
+ return null ;
274
+ }
275
+ }
276
+ if ( ! config . runspaceId && ! config . runspaceName ) {
277
+ config . runspaceId = await vscode . commands . executeCommand ( "PowerShell.PickRunspace" , config . processId ) ;
278
+ // No runspace selected. Cancel attach.
279
+ if ( ! config . runspaceId ) {
280
+ return null ;
281
+ }
282
+ }
320
283
return config ;
321
284
}
322
285
}
0 commit comments