in src/goMain.ts [125:719]
export async function activate(ctx: vscode.ExtensionContext): Promise<ExtensionAPI> {
if (process.env['VSCODE_GO_IN_TEST'] === '1') {
// Make sure this does not run when running in test.
return;
}
setGlobalState(ctx.globalState);
setWorkspaceState(ctx.workspaceState);
setEnvironmentVariableCollection(ctx.environmentVariableCollection);
const cfg = getGoConfig();
setLogConfig(cfg['logging']);
if (vscode.window.registerWebviewPanelSerializer) {
// Make sure we register a serializer in activation event
vscode.window.registerWebviewPanelSerializer(WelcomePanel.viewType, {
async deserializeWebviewPanel(webviewPanel: vscode.WebviewPanel, state: any) {
WelcomePanel.revive(webviewPanel, ctx.extensionUri);
}
});
}
if (isInPreviewMode()) {
// For Nightly extension users, show a message directing them to forums
// to give feedback.
setTimeout(showGoNightlyWelcomeMessage, 10 * timeMinute);
}
// Show the Go welcome page on update.
if (!IsInCloudIDE) {
showGoWelcomePage(ctx);
}
const configGOROOT = getGoConfig()['goroot'];
if (configGOROOT) {
// We don't support unsetting go.goroot because we don't know whether
// !configGOROOT case indicates the user wants to unset process.env['GOROOT']
// or the user wants the extension to use the current process.env['GOROOT'] value.
// TODO(hyangah): consider utilizing an empty value to indicate unset?
await setGOROOTEnvVar(configGOROOT);
}
// Present a warning about the deprecation of the go.documentLink setting.
const experimentalFeatures = getGoConfig()['languageServerExperimentalFeatures'];
if (experimentalFeatures) {
// TODO(golang/vscode-go#50): Eventually notify about deprecation of
// all of the settings. See golang/vscode-go#1109 too.
// The `diagnostics` setting is still used as a workaround for running custom vet.
if (experimentalFeatures['documentLink'] === false) {
vscode.window
.showErrorMessage(`The 'go.languageServerExperimentalFeature.documentLink' setting is now deprecated.
Please use '"gopls": {"ui.navigation.importShortcut": "Definition" }' instead.
See [the settings doc](https://github.com/golang/vscode-go/blob/master/docs/settings.md#uinavigationimportshortcut) for more details.`);
}
const promptKey = 'promptedLanguageServerExperimentalFeatureDeprecation';
const prompted = getFromGlobalState(promptKey, false);
if (!prompted && experimentalFeatures['diagnostics'] === false) {
const msg = `The 'go.languageServerExperimentalFeature.diagnostics' setting will be deprecated soon.
If you would like additional configuration for diagnostics from gopls, please see and response to [Issue 50](https://github.com/golang/vscode-go/issues/50).`;
const selected = await vscode.window.showInformationMessage(msg, "Don't show again");
switch (selected) {
case "Don't show again":
updateGlobalState(promptKey, true);
}
}
}
// Present a warning about the deprecation of a 'dlv-dap' binary setting.
checkAlternateTools(cfg);
updateGoVarsFromConfig().then(async () => {
suggestUpdates(ctx);
offerToInstallLatestGoVersion();
offerToInstallTools();
await configureLanguageServer(ctx);
if (
!languageServerIsRunning &&
vscode.window.activeTextEditor &&
vscode.window.activeTextEditor.document.languageId === 'go' &&
isGoPathSet()
) {
// Check mod status so that cache is updated and then run build/lint/vet
isModSupported(vscode.window.activeTextEditor.document.uri).then(() => {
runBuilds(vscode.window.activeTextEditor.document, getGoConfig());
});
}
});
initCoverageDecorators(ctx);
ctx.subscriptions.push(
vscode.commands.registerCommand('go.environment.status', async () => {
expandGoStatusBar();
})
);
const testCodeLensProvider = new GoRunTestCodeLensProvider();
const referencesCodeLensProvider = new GoReferencesCodeLensProvider();
ctx.subscriptions.push(vscode.languages.registerCodeLensProvider(GO_MODE, testCodeLensProvider));
ctx.subscriptions.push(vscode.languages.registerCodeLensProvider(GO_MODE, referencesCodeLensProvider));
// debug
ctx.subscriptions.push(
vscode.debug.registerDebugConfigurationProvider('go', new GoDebugConfigurationProvider('go'))
);
ctx.subscriptions.push(
vscode.commands.registerCommand(
'go.debug.pickProcess',
async (): Promise<string> => {
return await pickProcess();
}
)
);
ctx.subscriptions.push(
vscode.commands.registerCommand(
'go.debug.pickGoProcess',
async (): Promise<string> => {
return await pickGoProcess();
}
)
);
const debugOutputChannel = vscode.window.createOutputChannel('Go Debug');
ctx.subscriptions.push(debugOutputChannel);
const factory = new GoDebugAdapterDescriptorFactory(debugOutputChannel);
ctx.subscriptions.push(vscode.debug.registerDebugAdapterDescriptorFactory('go', factory));
if ('dispose' in factory) {
ctx.subscriptions.push(factory);
}
const tracker = new GoDebugAdapterTrackerFactory(debugOutputChannel);
ctx.subscriptions.push(vscode.debug.registerDebugAdapterTrackerFactory('go', tracker));
if ('dispose' in tracker) {
ctx.subscriptions.push(tracker);
}
buildDiagnosticCollection = vscode.languages.createDiagnosticCollection('go');
ctx.subscriptions.push(buildDiagnosticCollection);
lintDiagnosticCollection = vscode.languages.createDiagnosticCollection(
lintDiagnosticCollectionName(getGoConfig()['lintTool'])
);
ctx.subscriptions.push(lintDiagnosticCollection);
vetDiagnosticCollection = vscode.languages.createDiagnosticCollection('go-vet');
ctx.subscriptions.push(vetDiagnosticCollection);
addOnChangeTextDocumentListeners(ctx);
addOnChangeActiveTextEditorListeners(ctx);
addOnSaveTextDocumentListeners(ctx);
ctx.subscriptions.push(
vscode.commands.registerCommand('go.gopath', () => {
getCurrentGoPathCommand();
})
);
ctx.subscriptions.push(
vscode.commands.registerCommand('go.locate.tools', async () => {
getConfiguredGoToolsCommand();
})
);
ctx.subscriptions.push(
vscode.commands.registerCommand('go.add.tags', (args) => {
addTags(args);
})
);
ctx.subscriptions.push(
vscode.commands.registerCommand('go.remove.tags', (args) => {
removeTags(args);
})
);
ctx.subscriptions.push(
vscode.commands.registerCommand('go.fill.struct', () => {
runFillStruct(vscode.window.activeTextEditor);
})
);
ctx.subscriptions.push(
vscode.commands.registerCommand('go.impl.cursor', () => {
implCursor();
})
);
ctx.subscriptions.push(
vscode.commands.registerCommand('go.godoctor.extract', () => {
extractFunction();
})
);
ctx.subscriptions.push(
vscode.commands.registerCommand('go.godoctor.var', () => {
extractVariable();
})
);
ctx.subscriptions.push(
vscode.commands.registerCommand('go.test.cursor', (args) => {
const goConfig = getGoConfig();
testAtCursor(goConfig, 'test', args);
})
);
ctx.subscriptions.push(
vscode.commands.registerCommand('go.test.cursorOrPrevious', (args) => {
const goConfig = getGoConfig();
testAtCursorOrPrevious(goConfig, 'test', args);
})
);
if (isVscodeTestingAPIAvailable && cfg.get<boolean>('testExplorer.enable')) {
GoTestExplorer.setup(ctx);
}
ctx.subscriptions.push(
vscode.commands.registerCommand('go.subtest.cursor', (args) => {
const goConfig = getGoConfig();
subTestAtCursor(goConfig, args);
})
);
ctx.subscriptions.push(
vscode.commands.registerCommand('go.debug.cursor', (args) => {
const goConfig = getGoConfig();
testAtCursor(goConfig, 'debug', args);
})
);
ctx.subscriptions.push(
vscode.commands.registerCommand('go.benchmark.cursor', (args) => {
const goConfig = getGoConfig();
testAtCursor(goConfig, 'benchmark', args);
})
);
ctx.subscriptions.push(
vscode.commands.registerCommand('go.test.package', (args) => {
const goConfig = getGoConfig();
const isBenchmark = false;
testCurrentPackage(goConfig, isBenchmark, args);
})
);
ctx.subscriptions.push(
vscode.commands.registerCommand('go.benchmark.package', (args) => {
const goConfig = getGoConfig();
const isBenchmark = true;
testCurrentPackage(goConfig, isBenchmark, args);
})
);
ctx.subscriptions.push(
vscode.commands.registerCommand('go.test.file', (args) => {
const goConfig = getGoConfig();
const isBenchmark = false;
testCurrentFile(goConfig, isBenchmark, args);
})
);
ctx.subscriptions.push(
vscode.commands.registerCommand('go.benchmark.file', (args) => {
const goConfig = getGoConfig();
const isBenchmark = true;
testCurrentFile(goConfig, isBenchmark, args);
})
);
ctx.subscriptions.push(
vscode.commands.registerCommand('go.test.workspace', (args) => {
const goConfig = getGoConfig();
testWorkspace(goConfig, args);
})
);
ctx.subscriptions.push(
vscode.commands.registerCommand('go.test.previous', () => {
testPrevious();
})
);
ctx.subscriptions.push(
vscode.commands.registerCommand('go.debug.previous', () => {
debugPrevious();
})
);
ctx.subscriptions.push(
vscode.commands.registerCommand('go.test.coverage', () => {
toggleCoverageCurrentPackage();
})
);
ctx.subscriptions.push(
vscode.commands.registerCommand('go.test.showOutput', () => {
showTestOutput();
})
);
ctx.subscriptions.push(
vscode.commands.registerCommand('go.test.cancel', () => {
cancelRunningTests();
})
);
ctx.subscriptions.push(
vscode.commands.registerCommand('go.import.add', (arg) => {
return addImport(arg);
})
);
ctx.subscriptions.push(
vscode.commands.registerCommand('go.add.package.workspace', () => {
addImportToWorkspace();
})
);
ctx.subscriptions.push(
vscode.commands.registerCommand('go.tools.install', async (args) => {
if (Array.isArray(args) && args.length) {
const goVersion = await getGoVersion();
await installTools(args, goVersion);
return;
}
installAllTools();
})
);
ctx.subscriptions.push(
vscode.commands.registerCommand('go.browse.packages', () => {
browsePackages();
})
);
ctx.subscriptions.push(
vscode.workspace.onDidChangeConfiguration(async (e: vscode.ConfigurationChangeEvent) => {
if (!e.affectsConfiguration('go')) {
return;
}
const updatedGoConfig = getGoConfig();
if (e.affectsConfiguration('go.goroot')) {
const configGOROOT = updatedGoConfig['goroot'];
if (configGOROOT) {
await setGOROOTEnvVar(configGOROOT);
}
}
if (
e.affectsConfiguration('go.goroot') ||
e.affectsConfiguration('go.alternateTools') ||
e.affectsConfiguration('go.gopath') ||
e.affectsConfiguration('go.toolsEnvVars') ||
e.affectsConfiguration('go.testEnvFile')
) {
updateGoVarsFromConfig();
}
if (e.affectsConfiguration('go.logging')) {
setLogConfig(updatedGoConfig['logging']);
}
// If there was a change in "toolsGopath" setting, then clear cache for go tools
if (getToolsGopath() !== getToolsGopath(false)) {
clearCacheForTools();
}
if (updatedGoConfig['enableCodeLens']) {
testCodeLensProvider.setEnabled(updatedGoConfig['enableCodeLens']['runtest']);
referencesCodeLensProvider.setEnabled(updatedGoConfig['enableCodeLens']['references']);
}
if (e.affectsConfiguration('go.formatTool')) {
checkToolExists(getFormatTool(updatedGoConfig));
}
if (e.affectsConfiguration('go.lintTool')) {
checkToolExists(updatedGoConfig['lintTool']);
}
if (e.affectsConfiguration('go.docsTool')) {
checkToolExists(updatedGoConfig['docsTool']);
}
if (e.affectsConfiguration('go.coverageDecorator')) {
updateCodeCoverageDecorators(updatedGoConfig['coverageDecorator']);
}
if (e.affectsConfiguration('go.toolsEnvVars')) {
const env = toolExecutionEnvironment();
if (GO111MODULE !== env['GO111MODULE']) {
const reloadMsg =
'Reload VS Code window so that the Go tools can respect the change to GO111MODULE';
vscode.window.showInformationMessage(reloadMsg, 'Reload').then((selected) => {
if (selected === 'Reload') {
vscode.commands.executeCommand('workbench.action.reloadWindow');
}
});
}
}
if (e.affectsConfiguration('go.lintTool')) {
const lintTool = lintDiagnosticCollectionName(updatedGoConfig['lintTool']);
if (lintDiagnosticCollection && lintDiagnosticCollection.name !== lintTool) {
lintDiagnosticCollection.dispose();
lintDiagnosticCollection = vscode.languages.createDiagnosticCollection(lintTool);
ctx.subscriptions.push(lintDiagnosticCollection);
// TODO: actively maintain our own disposables instead of keeping pushing to ctx.subscription.
}
}
if (e.affectsConfiguration('go.testExplorer.enable')) {
const msg =
'Go test explorer has been enabled or disabled. For this change to take effect, the window must be reloaded.';
vscode.window.showInformationMessage(msg, 'Reload').then((selected) => {
if (selected === 'Reload') {
vscode.commands.executeCommand('workbench.action.reloadWindow');
}
});
}
})
);
ctx.subscriptions.push(
vscode.commands.registerCommand('go.test.generate.package', () => {
goGenerateTests.generateTestCurrentPackage();
})
);
ctx.subscriptions.push(
vscode.commands.registerCommand('go.test.generate.file', () => {
goGenerateTests.generateTestCurrentFile();
})
);
ctx.subscriptions.push(
vscode.commands.registerCommand('go.test.generate.function', () => {
goGenerateTests.generateTestCurrentFunction();
})
);
ctx.subscriptions.push(
vscode.commands.registerCommand('go.toggle.test.file', () => {
goGenerateTests.toggleTestFile();
})
);
ctx.subscriptions.push(
vscode.commands.registerCommand('go.debug.startSession', (config) => {
let workspaceFolder;
if (vscode.window.activeTextEditor) {
workspaceFolder = vscode.workspace.getWorkspaceFolder(vscode.window.activeTextEditor.document.uri);
}
return vscode.debug.startDebugging(workspaceFolder, config);
})
);
ctx.subscriptions.push(
vscode.commands.registerCommand('go.show.commands', () => {
const extCommands = getExtensionCommands();
extCommands.push({
command: 'editor.action.goToDeclaration',
title: 'Go to Definition'
});
extCommands.push({
command: 'editor.action.goToImplementation',
title: 'Go to Implementation'
});
extCommands.push({
command: 'workbench.action.gotoSymbol',
title: 'Go to Symbol in File...'
});
extCommands.push({
command: 'workbench.action.showAllSymbols',
title: 'Go to Symbol in Workspace...'
});
vscode.window.showQuickPick(extCommands.map((x) => x.title)).then((cmd) => {
const selectedCmd = extCommands.find((x) => x.title === cmd);
if (selectedCmd) {
vscode.commands.executeCommand(selectedCmd.command);
}
});
})
);
ctx.subscriptions.push(vscode.commands.registerCommand('go.get.package', goGetPackage));
ctx.subscriptions.push(vscode.commands.registerCommand('go.playground', playgroundCommand));
ctx.subscriptions.push(vscode.commands.registerCommand('go.lint.package', () => lintCode('package')));
ctx.subscriptions.push(vscode.commands.registerCommand('go.lint.workspace', () => lintCode('workspace')));
ctx.subscriptions.push(vscode.commands.registerCommand('go.lint.file', () => lintCode('file')));
ctx.subscriptions.push(vscode.commands.registerCommand('go.vet.package', vetCode));
ctx.subscriptions.push(vscode.commands.registerCommand('go.vet.workspace', () => vetCode(true)));
ctx.subscriptions.push(vscode.commands.registerCommand('go.build.package', buildCode));
ctx.subscriptions.push(vscode.commands.registerCommand('go.build.workspace', () => buildCode(true)));
ctx.subscriptions.push(vscode.commands.registerCommand('go.install.package', installCurrentPackage));
ctx.subscriptions.push(vscode.commands.registerCommand('go.run.modinit', goModInit));
ctx.subscriptions.push(
vscode.commands.registerCommand('go.extractServerChannel', () => {
showServerOutputChannel();
})
);
ctx.subscriptions.push(
vscode.commands.registerCommand('go.welcome', () => {
WelcomePanel.createOrShow(ctx.extensionUri);
})
);
ctx.subscriptions.push(
vscode.commands.registerCommand('go.workspace.resetState', () => {
resetWorkspaceState();
})
);
ctx.subscriptions.push(
vscode.commands.registerCommand('go.global.resetState', () => {
resetGlobalState();
})
);
ctx.subscriptions.push(
vscode.commands.registerCommand('go.toggle.gc_details', () => {
if (!languageServerIsRunning) {
vscode.window.showErrorMessage(
'"Go: Toggle gc details" command is available only when the language server is running'
);
return;
}
const doc = vscode.window.activeTextEditor?.document.uri.toString();
if (!doc || !doc.endsWith('.go')) {
vscode.window.showErrorMessage('"Go: Toggle gc details" command cannot run when no Go file is open.');
return;
}
vscode.commands.executeCommand('gc_details', doc).then(undefined, (reason0) => {
vscode.commands.executeCommand('gopls.gc_details', doc).then(undefined, (reason1) => {
vscode.window.showErrorMessage(
`"Go: Toggle gc details" command failed: gc_details:${reason0} gopls_gc_details:${reason1}`
);
});
});
})
);
ctx.subscriptions.push(
vscode.commands.registerCommand('go.apply.coverprofile', () => {
if (!vscode.window.activeTextEditor || !vscode.window.activeTextEditor.document.fileName.endsWith('.go')) {
vscode.window.showErrorMessage('Cannot apply coverage profile when no Go file is open.');
return;
}
const lastCoverProfilePathKey = 'lastCoverProfilePathKey';
const lastCoverProfilePath = getFromWorkspaceState(lastCoverProfilePathKey, '');
vscode.window
.showInputBox({
prompt: 'Enter the path to the coverage profile for current package',
value: lastCoverProfilePath
})
.then((coverProfilePath) => {
if (!coverProfilePath) {
return;
}
if (!fileExists(coverProfilePath)) {
vscode.window.showErrorMessage(`Cannot find the file ${coverProfilePath}`);
return;
}
if (coverProfilePath !== lastCoverProfilePath) {
updateWorkspaceState(lastCoverProfilePathKey, coverProfilePath);
}
applyCodeCoverageToAllEditors(
coverProfilePath,
getWorkspaceFolderPath(vscode.window.activeTextEditor.document.uri)
);
});
})
);
// Go Enviornment switching commands
ctx.subscriptions.push(
vscode.commands.registerCommand('go.environment.choose', () => {
chooseGoEnvironment();
})
);
// Survey related commands
ctx.subscriptions.push(vscode.commands.registerCommand('go.survey.showConfig', () => showSurveyConfig()));
ctx.subscriptions.push(vscode.commands.registerCommand('go.survey.resetConfig', () => resetSurveyConfigs()));
vscode.languages.setLanguageConfiguration(GO_MODE.language, {
wordPattern: /(-?\d*\.\d\w*)|([^`~!@#%^&*()\-=+[{\]}\\|;:'",.<>/?\s]+)/g
});
return extensionAPI;
}