blob: 7812323b2c36e82996706e8e240fa3da45f18267 [file] [log] [blame]
/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable @typescript-eslint/no-explicit-any */
/*---------------------------------------------------------
* Copyright (C) Microsoft Corporation. All rights reserved.
* Modification copyright 2020 The Go Authors. All rights reserved.
* Licensed under the MIT License. See LICENSE in the project root for license information.
*--------------------------------------------------------*/
'use strict';
import * as path from 'path';
import { extensionInfo, getGoConfig, getGoplsConfig } from './config';
import { browsePackages } from './goBrowsePackage';
import { buildCode } from './goBuild';
import { check, notifyIfGeneratedFile, removeTestStatus } from './goCheck';
import {
applyCodeCoverage,
initCoverageDecorators,
removeCodeCoverageOnFileSave,
toggleCoverageCurrentPackage,
trackCodeCoverageRemovalOnFileChange,
updateCodeCoverageDecorators
} from './goCover';
import { GoDebugConfigurationProvider } from './goDebugConfiguration';
import { GoDebugAdapterDescriptorFactory, GoDebugAdapterTrackerFactory } from './goDebugFactory';
import { extractFunction, extractVariable } from './goDoctor';
import { toolExecutionEnvironment } from './goEnv';
import {
chooseGoEnvironment,
offerToInstallLatestGoVersion,
setEnvironmentVariableCollection
} from './goEnvironmentStatus';
import { runFillStruct } from './goFillStruct';
import * as goGenerateTests from './goGenerateTests';
import { goGetPackage } from './goGetPackage';
import { implCursor } from './goImpl';
import { addImport, addImportToWorkspace } from './goImport';
import { installCurrentPackage } from './goInstall';
import {
inspectGoToolVersion,
installTools,
offerToInstallTools,
promptForMissingTool,
updateGoVarsFromConfig
} from './goInstallTools';
import { RestartReason, showServerOutputChannel, watchLanguageServerConfiguration } from './language/goLanguageServer';
import { lintCode } from './goLint';
import { logVerbose, setLogConfig } from './goLogging';
import { GO_MODE } from './goMode';
import { addTags, removeTags } from './goModifytags';
import { GO111MODULE, goModInit, isModSupported } from './goModules';
import { playgroundCommand } from './goPlayground';
import { GoReferencesCodeLensProvider } from './goReferencesCodelens';
import { GoRunTestCodeLensProvider } from './goRunTestCodelens';
import { disposeGoStatusBar, expandGoStatusBar, updateGoStatusBar } from './goStatus';
import {
debugPrevious,
subTestAtCursor,
testAtCursor,
testAtCursorOrPrevious,
testCurrentFile,
testCurrentPackage,
testPrevious,
testWorkspace
} from './goTest';
import { getConfiguredTools, Tool } from './goTools';
import { vetCode } from './goVet';
import { pickGoProcess, pickProcess } from './pickProcess';
import {
getFromGlobalState,
resetGlobalState,
resetWorkspaceState,
setGlobalState,
setWorkspaceState,
updateGlobalState
} from './stateUtils';
import { cancelRunningTests, showTestOutput } from './testUtils';
import {
cleanupTempDir,
getBinPath,
getGoVersion,
getToolsGopath,
GoVersion,
handleDiagnosticErrors,
isGoPathSet,
resolvePath
} from './util';
import { clearCacheForTools, dirExists } from './utils/pathUtils';
import { WelcomePanel } from './welcome';
import semver = require('semver');
import vscode = require('vscode');
import { getFormatTool } from './language/legacy/goFormat';
import { resetSurveyConfigs, showSurveyConfig } from './goSurvey';
import { ExtensionAPI } from './export';
import extensionAPI from './extensionAPI';
import { GoTestExplorer, isVscodeTestingAPIAvailable } from './goTest/explore';
import { killRunningPprof } from './goTest/profile';
import { GoExplorerProvider } from './goExplorer';
import { VulncheckProvider } from './goVulncheck';
import { GoExtensionContext } from './context';
import * as commands from './commands';
// TODO: Remove this export. Temporarily exporting the context for import into the
// legacy DocumentSymbolProvider.
export const goCtx: GoExtensionContext = {
lastUserAction: new Date(),
crashCount: 0,
restartHistory: []
};
export let buildDiagnosticCollection: vscode.DiagnosticCollection;
export let lintDiagnosticCollection: vscode.DiagnosticCollection;
export let vetDiagnosticCollection: vscode.DiagnosticCollection;
export async function activate(ctx: vscode.ExtensionContext): Promise<ExtensionAPI | undefined> {
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']);
WelcomePanel.activate(ctx, goCtx);
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);
}
}
}
return activateContinued(ctx, cfg);
}
async function activateContinued(
ctx: vscode.ExtensionContext,
cfg: vscode.WorkspaceConfiguration
): Promise<ExtensionAPI> {
await updateGoVarsFromConfig(goCtx);
suggestUpdates(ctx);
offerToInstallLatestGoVersion();
offerToInstallTools();
await commands.startLanguageServer(ctx, goCtx)(RestartReason.ACTIVATION);
const activeDoc = vscode.window.activeTextEditor?.document;
if (!goCtx.languageServerIsRunning && activeDoc?.languageId === 'go' && isGoPathSet()) {
// Check mod status so that cache is updated and then run build/lint/vet
isModSupported(activeDoc.uri).then(() => {
runBuilds(activeDoc, getGoConfig());
});
}
initCoverageDecorators(ctx);
const registerCommand = commands.createRegisterCommand(ctx, goCtx);
registerCommand('go.languageserver.restart', commands.startLanguageServer);
// Subscribe to notifications for changes to the configuration
// of the language server, even if it's not currently in use.
ctx.subscriptions.push(
vscode.workspace.onDidChangeConfiguration((e) => watchLanguageServerConfiguration(goCtx, e))
);
registerCommand('go.environment.status', (_ctx, goCtx) => () => expandGoStatusBar(goCtx));
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'))
);
registerCommand('go.debug.pickProcess', () => pickProcess);
registerCommand('go.debug.pickGoProcess', () => 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);
registerCommand('go.gopath', commands.getCurrentGoPath);
registerCommand('go.locate.tools', commands.getConfiguredGoTools);
registerCommand('go.add.tags', () => addTags);
registerCommand('go.remove.tags', () => removeTags);
registerCommand('go.fill.struct', () => () => runFillStruct(vscode.window.activeTextEditor));
registerCommand('go.impl.cursor', () => implCursor);
registerCommand('go.godoctor.extract', () => extractFunction);
registerCommand('go.godoctor.var', () => extractVariable);
registerCommand('go.test.cursor', () => (args) => testAtCursor(getGoConfig(), 'test', args));
registerCommand('go.test.cursorOrPrevious', () => (args) => testAtCursorOrPrevious(getGoConfig(), 'test', args));
if (isVscodeTestingAPIAvailable && cfg.get<boolean>('testExplorer.enable')) {
GoTestExplorer.setup(ctx);
}
GoExplorerProvider.setup(ctx);
VulncheckProvider.setup(ctx, goCtx);
registerCommand('go.subtest.cursor', () => (args) => subTestAtCursor(getGoConfig(), args));
registerCommand('go.debug.cursor', () => (args) => testAtCursor(getGoConfig(), 'debug', args));
registerCommand('go.benchmark.cursor', () => (args) => testAtCursor(getGoConfig(), 'benchmark', args));
registerCommand('go.test.package', () => (args) => testCurrentPackage(getGoConfig(), false, args));
registerCommand('go.benchmark.package', () => (args) => testCurrentPackage(getGoConfig(), true, args));
registerCommand('go.test.file', () => (args) => testCurrentFile(getGoConfig(), false, args));
registerCommand('go.benchmark.file', () => (args) => testCurrentFile(getGoConfig(), true, args));
registerCommand('go.test.workspace', () => (args) => testWorkspace(getGoConfig(), args));
registerCommand('go.test.previous', () => testPrevious);
registerCommand('go.debug.previous', () => debugPrevious);
registerCommand('go.test.coverage', () => toggleCoverageCurrentPackage);
registerCommand('go.test.showOutput', () => showTestOutput);
registerCommand('go.test.cancel', () => cancelRunningTests);
registerCommand('go.import.add', () => (arg) => addImport(goCtx, arg));
registerCommand('go.add.package.workspace', () => addImportToWorkspace);
registerCommand('go.tools.install', commands.installTools);
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(goCtx);
}
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');
}
});
}
})
);
registerCommand('go.test.generate.package', () => goGenerateTests.generateTestCurrentPackage);
registerCommand('go.test.generate.file', () => goGenerateTests.generateTestCurrentFile);
registerCommand('go.test.generate.function', () => goGenerateTests.generateTestCurrentFunction);
registerCommand('go.toggle.test.file', () => goGenerateTests.toggleTestFile);
registerCommand('go.debug.startSession', commands.startDebugSession);
registerCommand('go.show.commands', commands.showCommands);
registerCommand('go.get.package', () => goGetPackage);
registerCommand('go.playground', () => playgroundCommand);
registerCommand('go.lint.package', () => () => lintCode('package'));
registerCommand('go.lint.workspace', () => () => lintCode('workspace'));
registerCommand('go.lint.file', () => () => lintCode('file'));
registerCommand('go.vet.package', () => vetCode);
registerCommand('go.vet.workspace', () => () => vetCode(true));
registerCommand('go.build.package', () => buildCode);
registerCommand('go.build.workspace', () => () => buildCode(true));
registerCommand('go.install.package', () => installCurrentPackage);
registerCommand('go.run.modinit', () => goModInit);
registerCommand('go.extractServerChannel', (_ctx, goCtx) => () => showServerOutputChannel(goCtx));
registerCommand('go.workspace.resetState', () => resetWorkspaceState);
registerCommand('go.global.resetState', () => resetGlobalState);
registerCommand('go.toggle.gc_details', commands.toggleGCDetails);
registerCommand('go.apply.coverprofile', commands.applyCoverprofile);
// Go Enviornment switching commands
registerCommand('go.environment.choose', () => chooseGoEnvironment);
// Survey related commands
registerCommand('go.survey.showConfig', (_ctx, goCtx) => () => showSurveyConfig(goCtx));
registerCommand('go.survey.resetConfig', () => resetSurveyConfigs);
vscode.languages.setLanguageConfiguration(GO_MODE.language, {
wordPattern: /(-?\d*\.\d\w*)|([^`~!@#%^&*()\-=+[{\]}\\|;:'",.<>/?\s]+)/g
});
return extensionAPI;
}
export function deactivate() {
return Promise.all([
cancelRunningTests(),
killRunningPprof(),
Promise.resolve(cleanupTempDir()),
Promise.resolve(disposeGoStatusBar())
]);
}
function runBuilds(document: vscode.TextDocument, goConfig: vscode.WorkspaceConfiguration) {
if (document.languageId !== 'go') {
return;
}
buildDiagnosticCollection.clear();
lintDiagnosticCollection.clear();
vetDiagnosticCollection.clear();
check(document.uri, goConfig)
.then((results) => {
results.forEach((result) => {
handleDiagnosticErrors(document, result.errors, result.diagnosticCollection);
});
})
.catch((err) => {
vscode.window.showInformationMessage('Error: ' + err);
});
}
function addOnSaveTextDocumentListeners(ctx: vscode.ExtensionContext) {
vscode.workspace.onDidSaveTextDocument(removeCodeCoverageOnFileSave, null, ctx.subscriptions);
vscode.workspace.onDidSaveTextDocument(
(document) => {
if (document.languageId !== 'go') {
return;
}
const session = vscode.debug.activeDebugSession;
if (session && session.type === 'go') {
const neverAgain = { title: "Don't Show Again" };
const ignoreActiveDebugWarningKey = 'ignoreActiveDebugWarningKey';
const ignoreActiveDebugWarning = getFromGlobalState(ignoreActiveDebugWarningKey);
if (!ignoreActiveDebugWarning) {
vscode.window
.showWarningMessage(
'A debug session is currently active. Changes to your Go files may result in unexpected behaviour.',
neverAgain
)
.then((result) => {
if (result === neverAgain) {
updateGlobalState(ignoreActiveDebugWarningKey, true);
}
});
}
}
if (vscode.window.visibleTextEditors.some((e) => e.document.fileName === document.fileName)) {
runBuilds(document, getGoConfig(document.uri));
}
},
null,
ctx.subscriptions
);
}
function addOnChangeTextDocumentListeners(ctx: vscode.ExtensionContext) {
vscode.workspace.onDidChangeTextDocument(trackCodeCoverageRemovalOnFileChange, null, ctx.subscriptions);
vscode.workspace.onDidChangeTextDocument(removeTestStatus, null, ctx.subscriptions);
vscode.workspace.onDidChangeTextDocument(notifyIfGeneratedFile, ctx, ctx.subscriptions);
}
function addOnChangeActiveTextEditorListeners(ctx: vscode.ExtensionContext) {
[updateGoStatusBar, applyCodeCoverage].forEach((listener) => {
// Call the listeners on initilization for current active text editor
if (vscode.window.activeTextEditor) {
listener(vscode.window.activeTextEditor);
}
vscode.window.onDidChangeActiveTextEditor(listener, null, ctx.subscriptions);
});
}
function checkToolExists(tool: string) {
if (tool === getBinPath(tool)) {
promptForMissingTool(tool);
}
}
// exported for testing
export async function listOutdatedTools(configuredGoVersion: GoVersion, allTools: Tool[]): Promise<Tool[]> {
if (!configuredGoVersion || !configuredGoVersion.sv) {
return [];
}
const { major, minor } = configuredGoVersion.sv;
const oldTools = await Promise.all(
allTools.map(async (tool) => {
const toolPath = getBinPath(tool.name);
if (!path.isAbsolute(toolPath)) {
return;
}
const m = await inspectGoToolVersion(toolPath);
if (!m) {
console.log(`failed to get go tool version: ${toolPath}`);
return;
}
const { goVersion } = m;
if (!goVersion) {
// TODO: we cannot tell whether the tool was compiled with a newer version of go
// or compiled in an unconventional way.
return;
}
const toolGoVersion = new GoVersion('', `go version ${goVersion} os/arch`);
if (!toolGoVersion || !toolGoVersion.sv) {
return tool;
}
if (
major > toolGoVersion.sv.major ||
(major === toolGoVersion.sv.major && minor > toolGoVersion.sv.minor)
) {
return tool;
}
// special case: if the tool was compiled with beta or rc, and the current
// go version is a stable version, let's ask to recompile.
if (
major === toolGoVersion.sv.major &&
minor === toolGoVersion.sv.minor &&
(goVersion.includes('beta') || goVersion.includes('rc')) &&
// We assume tools compiled with different rc/beta need to be recompiled.
// We test the inequality by checking whether the exact beta or rc version
// appears in the `go version` output. e.g.,
// configuredGoVersion.version goVersion(tool) update
// 'go version go1.18 ...' 'go1.18beta1' Yes
// 'go version go1.18beta1 ...' 'go1.18beta1' No
// 'go version go1.18beta2 ...' 'go1.18beta1' Yes
// 'go version go1.18rc1 ...' 'go1.18beta1' Yes
// 'go version go1.18rc1 ...' 'go1.18' No
// 'go version devel go1.18-deadbeaf ...' 'go1.18beta1' No (* rare)
!configuredGoVersion.version.includes(goVersion)
) {
return tool;
}
return;
})
);
return oldTools.filter((tool): tool is Tool => !!tool);
}
async function suggestUpdates(ctx: vscode.ExtensionContext) {
const configuredGoVersion = await getGoVersion();
if (!configuredGoVersion || configuredGoVersion.lt('1.12')) {
// User is using an ancient or a dev version of go. Don't suggest updates -
// user should know what they are doing.
return;
}
const allTools = getConfiguredTools(configuredGoVersion, getGoConfig(), getGoplsConfig());
const toolsToUpdate = await listOutdatedTools(configuredGoVersion, allTools);
if (toolsToUpdate.length === 0) {
return;
}
// If the user has opted in to automatic tool updates, we can update
// without prompting.
const toolsManagementConfig = getGoConfig()['toolsManagement'];
if (toolsManagementConfig && toolsManagementConfig['autoUpdate'] === true) {
installTools(toolsToUpdate, configuredGoVersion, true);
} else {
const updateToolsCmdText = 'Update tools';
const selected = await vscode.window.showWarningMessage(
`Tools (${toolsToUpdate.map((tool) => tool.name).join(', ')}) need recompiling to work with ${
configuredGoVersion.version
}`,
updateToolsCmdText
);
if (selected === updateToolsCmdText) {
installTools(toolsToUpdate, configuredGoVersion);
}
}
}
function lintDiagnosticCollectionName(lintToolName: string) {
if (!lintToolName || lintToolName === 'golint') {
return 'go-lint';
}
return `go-${lintToolName}`;
}
// set GOROOT env var. If necessary, shows a warning.
export async function setGOROOTEnvVar(configGOROOT: string) {
if (!configGOROOT) {
return;
}
const goroot = configGOROOT ? resolvePath(configGOROOT) : undefined;
const currentGOROOT = process.env['GOROOT'];
if (goroot === currentGOROOT) {
return;
}
if (!(await dirExists(goroot ?? ''))) {
vscode.window.showWarningMessage(`go.goroot setting is ignored. ${goroot} is not a valid GOROOT directory.`);
return;
}
const neverAgain = { title: "Don't Show Again" };
const ignoreGOROOTSettingWarningKey = 'ignoreGOROOTSettingWarning';
const ignoreGOROOTSettingWarning = getFromGlobalState(ignoreGOROOTSettingWarningKey);
if (!ignoreGOROOTSettingWarning) {
vscode.window
.showInformationMessage(
`"go.goroot" setting (${goroot}) will be applied and set the GOROOT environment variable.`,
neverAgain
)
.then((result) => {
if (result === neverAgain) {
updateGlobalState(ignoreGOROOTSettingWarningKey, true);
}
});
}
logVerbose(`setting GOROOT = ${goroot} (old value: ${currentGOROOT}) because "go.goroot": "${configGOROOT}"`);
if (goroot) {
process.env['GOROOT'] = goroot;
} else {
delete process.env.GOROOT;
}
}