@@ -62,14 +62,15 @@ import globals, { initialize } from './shared/extensionGlobals'
62
62
import { join } from 'path'
63
63
import { Experiments , Settings } from './shared/settings'
64
64
import { isReleaseVersion } from './shared/vscode/env'
65
- import { Commands , registerErrorHandler } from './shared/vscode/commands2'
66
- import { ToolkitError , isUserCancelledError , resolveErrorMessageToDisplay } from './shared/errors'
67
- import { Logging } from './shared/logger/commands'
65
+ import { Commands , registerErrorHandler as registerCommandErrorHandler } from './shared/vscode/commands2'
68
66
import { UriHandler } from './shared/vscode/uriHandler'
69
67
import { telemetry } from './shared/telemetry/telemetry'
70
68
import { Auth } from './auth/auth'
71
- import { showMessageWithUrl } from './shared/utilities/messages'
72
69
import { openUrl } from './shared/utilities/vsCodeUtils'
70
+ import { isUserCancelledError , resolveErrorMessageToDisplay , ToolkitError } from './shared/errors'
71
+ import { Logging } from './shared/logger/commands'
72
+ import { showMessageWithUrl } from './shared/utilities/messages'
73
+ import { registerWebviewErrorHandler } from './webviews/server'
73
74
74
75
let localize : nls . LocalizeFunc
75
76
@@ -89,9 +90,13 @@ export async function activate(context: vscode.ExtensionContext) {
89
90
)
90
91
globals . outputChannel = toolkitOutputChannel
91
92
92
- registerErrorHandler ( ( info , error ) => {
93
+ registerCommandErrorHandler ( ( info , error ) => {
93
94
const defaultMessage = localize ( 'AWS.generic.message.error' , 'Failed to run command: {0}' , info . id )
94
- handleError ( error , info . id , defaultMessage )
95
+ logAndShowError ( error , info . id , defaultMessage )
96
+ } )
97
+
98
+ registerWebviewErrorHandler ( ( error : unknown , webviewId : string , command : string ) => {
99
+ logAndShowWebviewError ( error , webviewId , command )
95
100
} )
96
101
97
102
if ( isCloud9 ( ) ) {
@@ -273,29 +278,6 @@ export async function activate(context: vscode.ExtensionContext) {
273
278
}
274
279
}
275
280
276
- // This is only being used for errors from commands although there's plenty of other places where it
277
- // could be used. It needs to be apart of some sort of `core` module that is guaranteed to initialize
278
- // prior to every other Toolkit component. Logging and telemetry would fit well within this core module.
279
- async function handleError ( error : unknown , topic : string , defaultMessage : string ) {
280
- if ( isUserCancelledError ( error ) ) {
281
- getLogger ( ) . verbose ( `${ topic } : user cancelled` )
282
- return
283
- }
284
- const logsItem = localize ( 'AWS.generic.message.viewLogs' , 'View Logs...' )
285
- const logId = getLogger ( ) . error ( `${ topic } : %s` , error )
286
- const message = resolveErrorMessageToDisplay ( error , defaultMessage )
287
-
288
- if ( error instanceof ToolkitError && error . documentationUri ) {
289
- await showMessageWithUrl ( message , error . documentationUri , 'View Documentation' , 'error' )
290
- } else {
291
- await vscode . window . showErrorMessage ( message , logsItem ) . then ( async resp => {
292
- if ( resp === logsItem ) {
293
- await Logging . declared . viewLogsAtMessage . execute ( logId )
294
- }
295
- } )
296
- }
297
- }
298
-
299
281
export async function deactivate ( ) {
300
282
await codewhispererShutdown ( )
301
283
await globals . telemetry . shutdown ( )
@@ -365,6 +347,56 @@ function wrapWithProgressForCloud9(channel: vscode.OutputChannel): (typeof vscod
365
347
}
366
348
}
367
349
350
+ /**
351
+ * Logs the error. Then determines what kind of error message should be shown, if
352
+ * at all.
353
+ *
354
+ * @param error The error itself
355
+ * @param topic The prefix of the error message
356
+ * @param defaultMessage The message to show if once cannot be resolved from the given error
357
+ *
358
+ * SIDE NOTE:
359
+ * This is only being used for errors from commands and webview, there's plenty of other places
360
+ * (explorer, nodes, ...) where it could be used. It needs to be apart of some sort of `core`
361
+ * module that is guaranteed to initialize prior to every other Toolkit component.
362
+ * Logging and telemetry would fit well within this core module.
363
+ */
364
+ export async function logAndShowError ( error : unknown , topic : string , defaultMessage : string ) {
365
+ if ( isUserCancelledError ( error ) ) {
366
+ getLogger ( ) . verbose ( `${ topic } : user cancelled` )
367
+ return
368
+ }
369
+ const logsItem = localize ( 'AWS.generic.message.viewLogs' , 'View Logs...' )
370
+ const logId = getLogger ( ) . error ( `${ topic } : %s` , error )
371
+ const message = resolveErrorMessageToDisplay ( error , defaultMessage )
372
+
373
+ if ( error instanceof ToolkitError && error . documentationUri ) {
374
+ await showMessageWithUrl ( message , error . documentationUri , 'View Documentation' , 'error' )
375
+ } else {
376
+ await vscode . window . showErrorMessage ( message , logsItem ) . then ( async resp => {
377
+ if ( resp === logsItem ) {
378
+ await Logging . declared . viewLogsAtMessage . execute ( logId )
379
+ }
380
+ } )
381
+ }
382
+ }
383
+
384
+ /**
385
+ * Show a webview related error to the user + button that links to the logged error
386
+ *
387
+ * @param err The error that was thrown in the backend
388
+ * @param webviewId Arbitrary value that identifies which webview had the error
389
+ * @param command The high level command/function that was run which triggered the error
390
+ */
391
+ export function logAndShowWebviewError ( err : unknown , webviewId : string , command : string ) {
392
+ // HACK: The following implementation is a hack, influenced by the implementation of handleError().
393
+ // The userFacingError message will be seen in the UI, and the detailedError message will provide the
394
+ // detailed information in the logs.
395
+ const detailedError = ToolkitError . chain ( err , `Webview backend command failed: "${ command } ()"` )
396
+ const userFacingError = ToolkitError . chain ( detailedError , 'Webview error' )
397
+ logAndShowError ( userFacingError , `webviewId="${ webviewId } "` , 'Webview error' )
398
+ }
399
+
368
400
// Unique extension entrypoint names, so that they can be obtained from the webpack bundle
369
401
export const awsToolkitActivate = activate
370
402
export const awsToolkitDeactivate = deactivate
0 commit comments