Skip to content

Commit 9da0a64

Browse files
browser: move more code in to shared activation (#4399)
This moves more code in to the shared activation method so that we should be able to start enabling CodeWhisperer (it should have all the pre-requisite setup it requires now) - Shared code was moved out of `extension.ts#activate()` and in to `extensionShared.ts#activateShared()` - The `ExtContext` object is now created in `activateShared()` and passed to the entrypoints as a return value <!--- REMINDER: - Read CONTRIBUTING.md first. - Add test coverage for your changes. - Update the changelog using `npm run newChange`. - Link to related issues/commits. - Testing: how did you test your changes? - Screenshots --> ## License By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license. --------- Signed-off-by: nkomonen <[email protected]>
1 parent 97cbf9b commit 9da0a64

File tree

4 files changed

+181
-148
lines changed

4 files changed

+181
-148
lines changed

packages/toolkit/src/extension.ts

Lines changed: 14 additions & 144 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ import { activate as activateSam } from './shared/sam/activation'
3333
import { activate as activateS3 } from './s3/activation'
3434
import * as awsFiletypes from './shared/awsFiletypes'
3535
import { activate as activateCodeWhisperer, shutdown as codewhispererShutdown } from './codewhisperer/activation'
36-
import { ExtContext } from './shared/extensions'
3736
import { activate as activateApiGateway } from './apigateway/activation'
3837
import { activate as activateStepFunctions } from './stepFunctions/activation'
3938
import { activate as activateSsmDocument } from './ssmDocument/activation'
@@ -46,7 +45,6 @@ import { activate as activateApplicationComposer } from './applicationcomposer/a
4645
import { activate as activateRedshift } from './redshift/activation'
4746
import { activate as activateCWChat } from './amazonq/activation'
4847
import { activate as activateQGumby } from './amazonqGumby/activation'
49-
import { getSamCliContext } from './shared/sam/cli/samCliContext'
5048
import { Ec2CredentialsProvider } from './auth/providers/ec2CredentialsProvider'
5149
import { EnvVarsCredentialsProvider } from './auth/providers/envVarsCredentialsProvider'
5250
import { EcsCredentialsProvider } from './auth/providers/ecsCredentialsProvider'
@@ -55,58 +53,31 @@ import { AwsResourceManager } from './dynamicResources/awsResourceManager'
5553
import globals from './shared/extensionGlobals'
5654
import { Experiments, Settings } from './shared/settings'
5755
import { isReleaseVersion } from './shared/vscode/env'
58-
import { Commands, registerErrorHandler as registerCommandErrorHandler } from './shared/vscode/commands2'
59-
import { UriHandler } from './shared/vscode/uriHandler'
6056
import { telemetry } from './shared/telemetry/telemetry'
6157
import { Auth } from './auth/auth'
62-
import { isUserCancelledError, resolveErrorMessageToDisplay, ToolkitError } from './shared/errors'
63-
import { Logging } from './shared/logger/commands'
64-
import { showMessageWithUrl, showViewLogsMessage } from './shared/utilities/messages'
65-
import { registerWebviewErrorHandler } from './webviews/server'
66-
import { ChildProcess } from './shared/utilities/childProcess'
58+
import { showViewLogsMessage } from './shared/utilities/messages'
6759
import { initializeNetworkAgent } from './codewhisperer/client/agent'
6860
import { Timeout } from './shared/utilities/timeoutUtils'
6961
import { submitFeedback } from './feedback/vue/submitFeedback'
70-
import { showQuickStartWebview } from './shared/extensionStartup'
71-
import { activateShared } from './extensionShared'
62+
import { activateShared, deactivateShared } from './extensionShared'
7263

7364
let localize: nls.LocalizeFunc
7465

66+
/**
67+
* The entrypoint for the nodejs version of the toolkit
68+
*
69+
* **CONTIBUTORS** If you are adding code to this function prioritize adding it to
70+
* {@link activateShared} if appropriate
71+
*/
7572
export async function activate(context: vscode.ExtensionContext) {
7673
const activationStartedOn = Date.now()
7774
localize = nls.loadMessageBundle()
7875

79-
globals.machineId = await getMachineId()
80-
81-
const remoteInvokeOutputChannel = vscode.window.createOutputChannel(
82-
localize('AWS.channel.aws.remoteInvoke', '{0} Remote Invocations', getIdeProperties().company)
83-
)
84-
85-
registerCommandErrorHandler((info, error) => {
86-
const defaultMessage = localize('AWS.generic.message.error', 'Failed to run command: {0}', info.id)
87-
void logAndShowError(error, info.id, defaultMessage)
88-
})
89-
90-
registerWebviewErrorHandler((error: unknown, webviewId: string, command: string) => {
91-
logAndShowWebviewError(error, webviewId, command)
92-
})
93-
94-
if (isCloud9()) {
95-
vscode.window.withProgress = wrapWithProgressForCloud9(globals.outputChannel)
96-
context.subscriptions.push(
97-
Commands.register('aws.quickStart', async () => {
98-
try {
99-
await showQuickStartWebview(context)
100-
} finally {
101-
telemetry.aws_helpQuickstart.emit({ result: 'Succeeded' })
102-
}
103-
})
104-
)
105-
}
106-
10776
try {
10877
// IMPORTANT: If you are doing setup that should also work in browser, it should be done in the function below
109-
await activateShared(context, () => RegionProvider.fromEndpointsProvider(makeEndpointsProvider()))
78+
const extContext = await activateShared(context, () =>
79+
RegionProvider.fromEndpointsProvider(makeEndpointsProvider())
80+
)
11081

11182
initializeNetworkAgent()
11283
initializeCredentialsProviderManager()
@@ -121,9 +92,6 @@ export async function activate(context: vscode.ExtensionContext) {
12192
globals.awsContextCommands = new AwsContextCommands(globals.regionProvider, Auth.instance)
12293
globals.schemaService = new SchemaService()
12394
globals.resourceManager = new AwsResourceManager(context)
124-
// Create this now, but don't call vscode.window.registerUriHandler() until after all
125-
// Toolkit services have a chance to register their path handlers. #4105
126-
globals.uriHandler = new UriHandler()
12795

12896
const settings = Settings.instance
12997
const experiments = Experiments.instance
@@ -139,18 +107,6 @@ export async function activate(context: vscode.ExtensionContext) {
139107
await globals.schemaService.start()
140108
awsFiletypes.activate()
141109

142-
const extContext: ExtContext = {
143-
extensionContext: context,
144-
awsContext: globals.awsContext,
145-
samCliContext: getSamCliContext,
146-
regionProvider: globals.regionProvider,
147-
outputChannel: globals.outputChannel,
148-
invokeOutputChannel: remoteInvokeOutputChannel,
149-
telemetryService: globals.telemetry,
150-
uriHandler: globals.uriHandler,
151-
credentialsStore: globals.loginManager.store,
152-
}
153-
154110
try {
155111
await activateDev(context)
156112
} catch (error) {
@@ -174,7 +130,7 @@ export async function activate(context: vscode.ExtensionContext) {
174130
context: extContext,
175131
regionProvider: globals.regionProvider,
176132
toolkitOutputChannel: globals.outputChannel,
177-
remoteInvokeOutputChannel,
133+
remoteInvokeOutputChannel: globals.invokeOutputChannel,
178134
})
179135

180136
await activateCodeWhisperer(extContext)
@@ -183,7 +139,7 @@ export async function activate(context: vscode.ExtensionContext) {
183139

184140
await activateApiGateway({
185141
extContext: extContext,
186-
outputChannel: remoteInvokeOutputChannel,
142+
outputChannel: globals.invokeOutputChannel,
187143
})
188144

189145
await activateLambda(extContext)
@@ -273,8 +229,8 @@ export async function activate(context: vscode.ExtensionContext) {
273229
}
274230

275231
export async function deactivate() {
232+
await deactivateShared()
276233
await codewhispererShutdown()
277-
await globals.telemetry.shutdown()
278234
await globals.resourceManager.dispose()
279235
}
280236

@@ -309,87 +265,6 @@ function recordToolkitInitialization(activationStartedOn: number, settingsValid:
309265
}
310266
}
311267

312-
/**
313-
* Wraps the `vscode.window.withProgress` functionality with functionality that also writes to the output channel.
314-
*
315-
* Cloud9 does not show a progress notification.
316-
*/
317-
function wrapWithProgressForCloud9(channel: vscode.OutputChannel): (typeof vscode.window)['withProgress'] {
318-
const withProgress = vscode.window.withProgress.bind(vscode.window)
319-
320-
return (options, task) => {
321-
if (options.title) {
322-
channel.appendLine(options.title)
323-
}
324-
325-
return withProgress(options, (progress, token) => {
326-
const newProgress: typeof progress = {
327-
...progress,
328-
report: value => {
329-
if (value.message) {
330-
channel.appendLine(value.message)
331-
}
332-
progress.report(value)
333-
},
334-
}
335-
336-
return task(newProgress, token)
337-
})
338-
}
339-
}
340-
341-
/**
342-
* Logs the error. Then determines what kind of error message should be shown, if
343-
* at all.
344-
*
345-
* @param error The error itself
346-
* @param topic The prefix of the error message
347-
* @param defaultMessage The message to show if once cannot be resolved from the given error
348-
*
349-
* SIDE NOTE:
350-
* This is only being used for errors from commands and webview, there's plenty of other places
351-
* (explorer, nodes, ...) where it could be used. It needs to be apart of some sort of `core`
352-
* module that is guaranteed to initialize prior to every other Toolkit component.
353-
* Logging and telemetry would fit well within this core module.
354-
*/
355-
export async function logAndShowError(error: unknown, topic: string, defaultMessage: string) {
356-
if (isUserCancelledError(error)) {
357-
getLogger().verbose(`${topic}: user cancelled`)
358-
return
359-
}
360-
const logsItem = localize('AWS.generic.message.viewLogs', 'View Logs...')
361-
const logId = getLogger().error(`${topic}: %s`, error)
362-
const message = resolveErrorMessageToDisplay(error, defaultMessage)
363-
364-
if (error instanceof ToolkitError && error.documentationUri) {
365-
await showMessageWithUrl(message, error.documentationUri, 'View Documentation', 'error')
366-
} else {
367-
await vscode.window.showErrorMessage(message, logsItem).then(async resp => {
368-
if (resp === logsItem) {
369-
await Logging.declared.viewLogsAtMessage.execute(logId)
370-
}
371-
})
372-
}
373-
}
374-
375-
/**
376-
* Show a webview related error to the user + button that links to the logged error
377-
*
378-
* @param err The error that was thrown in the backend
379-
* @param webviewId Arbitrary value that identifies which webview had the error
380-
* @param command The high level command/function that was run which triggered the error
381-
*/
382-
export function logAndShowWebviewError(err: unknown, webviewId: string, command: string) {
383-
// HACK: The following implementation is a hack, influenced by the implementation of handleError().
384-
// The userFacingError message will be seen in the UI, and the detailedError message will provide the
385-
// detailed information in the logs.
386-
const detailedError = ToolkitError.chain(err, `Webview backend command failed: "${command}()"`)
387-
const userFacingError = ToolkitError.chain(detailedError, 'Webview error')
388-
logAndShowError(userFacingError, `webviewId="${webviewId}"`, 'Webview error').catch(e => {
389-
getLogger().error('logAndShowError failed: %s', (e as Error).message)
390-
})
391-
}
392-
393268
async function checkSettingsHealth(settings: Settings): Promise<boolean> {
394269
const r = await settings.isValid()
395270
switch (r) {
@@ -415,11 +290,6 @@ async function checkSettingsHealth(settings: Settings): Promise<boolean> {
415290
}
416291
}
417292

418-
async function getMachineId(): Promise<string> {
419-
const proc = new ChildProcess('hostname', [], { collect: true, logging: 'no' })
420-
return (await proc.run()).stdout.trim() ?? 'unknown-host'
421-
}
422-
423293
// Unique extension entrypoint names, so that they can be obtained from the webpack bundle
424294
export const awsToolkitActivate = activate
425295
export const awsToolkitDeactivate = deactivate

0 commit comments

Comments
 (0)