src/language: create go extension context
The GoExtensionContext object will hold the shared state
related to the language client and server.
Change-Id: I1795f854f360af6809ca73637ac59cdd9b24c57e
Reviewed-on: https://go-review.googlesource.com/c/vscode-go/+/404075
Run-TryBot: Jamal Carvalho <jamal@golang.org>
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
TryBot-Result: kokoro <noreply+kokoro@google.com>
diff --git a/src/context.ts b/src/context.ts
new file mode 100644
index 0000000..a1bff86
--- /dev/null
+++ b/src/context.ts
@@ -0,0 +1,33 @@
+/*---------------------------------------------------------
+ * Copyright 2022 The Go Authors. All rights reserved.
+ * Licensed under the MIT License. See LICENSE in the project root for license information.
+ *--------------------------------------------------------*/
+
+import * as vscode from 'vscode';
+import { LanguageClient } from 'vscode-languageclient/node';
+
+import { LanguageServerConfig, Restart, ServerInfo } from './language/goLanguageServer';
+import { LegacyLanguageService } from './language/registerDefaultProviders';
+import { Mutex } from './utils/mutex';
+
+// Global variables used for management of the language client.
+// They are global so that the server can be easily restarted with
+// new configurations.
+export interface GoExtensionContext {
+ languageClient?: LanguageClient;
+ legacyLanguageService?: LegacyLanguageService;
+ languageServerDisposable?: vscode.Disposable;
+ latestConfig?: LanguageServerConfig;
+ serverOutputChannel?: vscode.OutputChannel;
+ languageServerIsRunning?: boolean;
+ // serverInfo is the information from the server received during initialization.
+ serverInfo?: ServerInfo;
+ // lastUserAction is the time of the last user-triggered change.
+ // A user-triggered change is a didOpen, didChange, didSave, or didClose event.
+ lastUserAction: Date;
+ serverTraceChannel?: vscode.OutputChannel;
+ crashCount: number;
+ // Some metrics for automated issue reports:
+ restartHistory: Restart[];
+ languageServerStartMutex: Mutex;
+}
diff --git a/src/goDeveloperSurvey.ts b/src/goDeveloperSurvey.ts
index ec942e8..4235606 100644
--- a/src/goDeveloperSurvey.ts
+++ b/src/goDeveloperSurvey.ts
@@ -8,8 +8,8 @@
import vscode = require('vscode');
import { getGoConfig } from './config';
-import { lastUserAction } from './language/goLanguageServer';
import { daysBetween, flushSurveyConfig, getStateConfig, minutesBetween, timeMinute } from './goSurvey';
+import { GoExtensionContext } from './context';
// Start and end dates of the survey.
export const startDate = new Date('2021-10-27');
@@ -35,7 +35,7 @@
lastDateAccepted?: Date;
}
-export function maybePromptForDeveloperSurvey() {
+export function maybePromptForDeveloperSurvey(goCtx: GoExtensionContext) {
// First, check the value of the 'go.survey.prompt' setting to see
// if the user has opted out of all survey prompts.
const goConfig = getGoConfig();
@@ -54,7 +54,7 @@
const currentTime = new Date();
// Make sure the user has been idle for at least a minute.
- if (minutesBetween(lastUserAction, currentTime) < 1) {
+ if (minutesBetween(goCtx.lastUserAction, currentTime) < 1) {
setTimeout(callback, 5 * timeMinute);
return;
}
diff --git a/src/goImport.ts b/src/goImport.ts
index 43d728e..e6d4520 100644
--- a/src/goImport.ts
+++ b/src/goImport.ts
@@ -12,11 +12,11 @@
import { ExecuteCommandRequest, ExecuteCommandParams } from 'vscode-languageserver-protocol';
import { toolExecutionEnvironment } from './goEnv';
import { promptForMissingTool } from './goInstallTools';
-import { languageClient, serverInfo } from './language/goLanguageServer';
import { documentSymbols, GoOutlineImportsOptions } from './language/legacy/goOutline';
import { getImportablePackages } from './goPackages';
import { getBinPath, getImportPath, parseFilePrelude } from './util';
import { envPath, getCurrentGoRoot } from './utils/pathUtils';
+import { GoExtensionContext } from './context';
const missingToolMsg = 'Missing tool: ';
@@ -44,7 +44,8 @@
return [...stdLibs.sort(), ...nonStdLibs.sort()];
}
-async function golist(): Promise<string[]> {
+async function golist(goCtx: GoExtensionContext): Promise<string[]> {
+ const { languageClient, serverInfo } = goCtx;
const COMMAND = 'gopls.list_known_packages';
if (languageClient && serverInfo?.Commands?.includes(COMMAND)) {
try {
@@ -96,9 +97,9 @@
return imports;
}
-async function askUserForImport(): Promise<string | undefined> {
+async function askUserForImport(goCtx: GoExtensionContext): Promise<string | undefined> {
try {
- const packages = await golist();
+ const packages = await golist(goCtx);
return vscode.window.showQuickPick(packages);
} catch (err) {
if (typeof err === 'string' && err.startsWith(missingToolMsg)) {
@@ -162,13 +163,14 @@
}
}
-export function addImport(arg: { importPath: string }) {
+export function addImport(goCtx: GoExtensionContext, arg: { importPath: string }) {
+ const { languageClient, serverInfo } = goCtx;
const editor = vscode.window.activeTextEditor;
if (!editor) {
vscode.window.showErrorMessage('No active editor found to add imports.');
return;
}
- const p = arg && arg.importPath ? Promise.resolve(arg.importPath) : askUserForImport();
+ const p = arg && arg.importPath ? Promise.resolve(arg.importPath) : askUserForImport(goCtx);
p.then(async (imp) => {
if (!imp) {
return;
diff --git a/src/goInstallTools.ts b/src/goInstallTools.ts
index b8b5853..f6485ea 100644
--- a/src/goInstallTools.ts
+++ b/src/goInstallTools.ts
@@ -17,6 +17,7 @@
import { toolExecutionEnvironment, toolInstallationEnvironment } from './goEnv';
import { addGoRuntimeBaseToPATH, clearGoRuntimeBaseFromPATH } from './goEnvironmentStatus';
import { logVerbose } from './goLogging';
+import { GoExtensionContext } from './context';
import { restartLanguageServer } from './goMain';
import { addGoStatus, initGoStatusBar, outputChannel, removeGoStatus } from './goStatus';
import {
@@ -512,7 +513,7 @@
}
}
-export function updateGoVarsFromConfig(): Promise<void> {
+export function updateGoVarsFromConfig(goCtx: GoExtensionContext): Promise<void> {
const { binPath, why } = getBinPathWithExplanation('go', false);
const goRuntimePath = binPath;
@@ -570,7 +571,7 @@
// clear pre-existing terminal PATH mutation logic set up by this extension.
clearGoRuntimeBaseFromPATH();
}
- initGoStatusBar();
+ initGoStatusBar(goCtx);
// TODO: restart language server or synchronize with language server update.
return resolve();
diff --git a/src/goMain.ts b/src/goMain.ts
index 22f06ec..7df094f 100644
--- a/src/goMain.ts
+++ b/src/goMain.ts
@@ -46,7 +46,6 @@
updateGoVarsFromConfig
} from './goInstallTools';
import {
- languageServerIsRunning,
RestartReason,
showServerOutputChannel,
startLanguageServerWithFallback,
@@ -104,7 +103,7 @@
import semver = require('semver');
import vscode = require('vscode');
import { getFormatTool } from './language/legacy/goFormat';
-import { resetSurveyConfigs, showSurveyConfig, timeMinute } from './goSurvey';
+import { resetSurveyConfigs, showSurveyConfig } from './goSurvey';
import { ExtensionAPI } from './export';
import extensionAPI from './extensionAPI';
import { GoTestExplorer, isVscodeTestingAPIAvailable } from './goTest/explore';
@@ -112,6 +111,18 @@
import { GoExplorerProvider } from './goExplorer';
import { VulncheckProvider } from './goVulncheck';
+import { Mutex } from './utils/mutex';
+import { GoExtensionContext } from './context';
+
+// TODO: Remove this export. Temporarily exporting the context for import into the
+// legacy DocumentSymbolProvider.
+export const goCtx: GoExtensionContext = {
+ lastUserAction: new Date(),
+ crashCount: 0,
+ restartHistory: [],
+ languageServerStartMutex: new Mutex()
+};
+
export let buildDiagnosticCollection: vscode.DiagnosticCollection;
export let lintDiagnosticCollection: vscode.DiagnosticCollection;
export let vetDiagnosticCollection: vscode.DiagnosticCollection;
@@ -196,17 +207,17 @@
ctx: vscode.ExtensionContext,
cfg: vscode.WorkspaceConfiguration
): Promise<ExtensionAPI> {
- await updateGoVarsFromConfig();
+ await updateGoVarsFromConfig(goCtx);
suggestUpdates(ctx);
offerToInstallLatestGoVersion();
offerToInstallTools();
// TODO: let configureLanguageServer to return its status.
- await configureLanguageServer(ctx);
+ await configureLanguageServer(ctx, goCtx);
const activeDoc = vscode.window.activeTextEditor?.document;
- if (!languageServerIsRunning && activeDoc?.languageId === 'go' && isGoPathSet()) {
+ 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());
@@ -217,7 +228,7 @@
ctx.subscriptions.push(
vscode.commands.registerCommand('go.environment.status', async () => {
- expandGoStatusBar();
+ expandGoStatusBar(goCtx);
})
);
const testCodeLensProvider = new GoRunTestCodeLensProvider();
@@ -342,7 +353,7 @@
}
GoExplorerProvider.setup(ctx);
- VulncheckProvider.setup(ctx);
+ VulncheckProvider.setup(ctx, goCtx);
ctx.subscriptions.push(
vscode.commands.registerCommand('go.subtest.cursor', (args) => {
@@ -436,7 +447,7 @@
ctx.subscriptions.push(
vscode.commands.registerCommand('go.import.add', (arg) => {
- return addImport(arg);
+ return addImport(goCtx, arg);
})
);
@@ -483,7 +494,7 @@
e.affectsConfiguration('go.toolsEnvVars') ||
e.affectsConfiguration('go.testEnvFile')
) {
- updateGoVarsFromConfig();
+ updateGoVarsFromConfig(goCtx);
}
if (e.affectsConfiguration('go.logging')) {
setLogConfig(updatedGoConfig['logging']);
@@ -630,7 +641,7 @@
ctx.subscriptions.push(
vscode.commands.registerCommand('go.extractServerChannel', () => {
- showServerOutputChannel();
+ showServerOutputChannel(goCtx);
})
);
@@ -648,7 +659,7 @@
ctx.subscriptions.push(
vscode.commands.registerCommand('go.toggle.gc_details', () => {
- if (!languageServerIsRunning) {
+ if (!goCtx.languageServerIsRunning) {
vscode.window.showErrorMessage(
'"Go: Toggle gc details" command is available only when the language server is running'
);
@@ -709,7 +720,7 @@
);
// Survey related commands
- ctx.subscriptions.push(vscode.commands.registerCommand('go.survey.showConfig', () => showSurveyConfig()));
+ ctx.subscriptions.push(vscode.commands.registerCommand('go.survey.showConfig', () => showSurveyConfig(goCtx)));
ctx.subscriptions.push(vscode.commands.registerCommand('go.survey.resetConfig', () => resetSurveyConfigs()));
vscode.languages.setLanguageConfiguration(GO_MODE.language, {
@@ -933,20 +944,22 @@
}
}
-function configureLanguageServer(ctx: vscode.ExtensionContext) {
+function configureLanguageServer(ctx: vscode.ExtensionContext, goCtx: GoExtensionContext) {
// 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(e)));
+ ctx.subscriptions.push(
+ vscode.workspace.onDidChangeConfiguration((e) => watchLanguageServerConfiguration(goCtx, e))
+ );
// Set the function that is used to restart the language server.
// This is necessary, even if the language server is not currently
// in use.
restartLanguageServer = async (reason: RestartReason) => {
- startLanguageServerWithFallback(ctx, reason);
+ startLanguageServerWithFallback(ctx, goCtx, reason);
};
// Start the language server, or fallback to the default language providers.
- return startLanguageServerWithFallback(ctx, 'activation');
+ return startLanguageServerWithFallback(ctx, goCtx, 'activation');
}
function getCurrentGoPathCommand() {
diff --git a/src/goStatus.ts b/src/goStatus.ts
index 56360e5..87807ab 100644
--- a/src/goStatus.ts
+++ b/src/goStatus.ts
@@ -11,16 +11,12 @@
import vscodeUri = require('vscode-uri');
import { getGoConfig } from './config';
import { formatGoVersion, GoEnvironmentOption, terminalCreationListener } from './goEnvironmentStatus';
-import {
- buildLanguageServerConfig,
- getLocalGoplsVersion,
- languageServerIsRunning,
- serverOutputChannel
-} from './language/goLanguageServer';
+import { buildLanguageServerConfig, getLocalGoplsVersion } from './language/goLanguageServer';
import { isGoFile } from './goMode';
import { isModSupported, runGoEnv } from './goModules';
import { allToolsInformation } from './goToolsInformation';
import { getGoVersion } from './util';
+import { GoExtensionContext } from './context';
export const outputChannel = vscode.window.createOutputChannel('Go');
@@ -57,7 +53,8 @@
}
}
-export async function expandGoStatusBar() {
+export async function expandGoStatusBar(goCtx: GoExtensionContext) {
+ const { languageServerIsRunning, serverOutputChannel } = goCtx;
const options = [
{ label: 'Locate Configured Go Tools', description: 'display go env' },
{ label: 'Choose Go Environment' }
@@ -120,7 +117,8 @@
/**
* Initialize the status bar item with current Go binary
*/
-export async function initGoStatusBar() {
+export async function initGoStatusBar(goCtx: GoExtensionContext) {
+ const { languageServerIsRunning } = goCtx;
if (!goEnvStatusbarItem) {
const STATUS_BAR_ITEM_NAME = 'Go';
goEnvStatusbarItem = vscode.window.createStatusBarItem(
@@ -141,7 +139,7 @@
// Assume if it is configured it is already running, since the
// icon will be updated on an attempt to start.
const goConfig = getGoConfig();
- updateLanguageServerIconGoStatusBar(languageServerIsRunning, goConfig['useLanguageServer'] === true);
+ updateLanguageServerIconGoStatusBar(!!languageServerIsRunning, goConfig['useLanguageServer'] === true);
showGoStatusBar();
}
diff --git a/src/goSurvey.ts b/src/goSurvey.ts
index b55c2d4..cf76bb0 100644
--- a/src/goSurvey.ts
+++ b/src/goSurvey.ts
@@ -7,7 +7,7 @@
'use strict';
import vscode = require('vscode');
-import { getLocalGoplsVersion, lastUserAction, latestConfig } from './language/goLanguageServer';
+import { getLocalGoplsVersion } from './language/goLanguageServer';
import { outputChannel } from './goStatus';
import { extensionId } from './const';
import { getFromGlobalState, getFromWorkspaceState, updateGlobalState } from './stateUtils';
@@ -19,6 +19,7 @@
} from './goDeveloperSurvey';
import { getGoConfig } from './config';
import { getGoVersion } from './util';
+import { GoExtensionContext } from './context';
// GoplsSurveyConfig is the set of global properties used to determine if
// we should prompt a user to take the gopls survey.
@@ -48,7 +49,7 @@
lastDateAccepted?: Date;
}
-export function maybePromptForGoplsSurvey() {
+export function maybePromptForGoplsSurvey(goCtx: GoExtensionContext) {
// First, check the value of the 'go.survey.prompt' setting to see
// if the user has opted out of all survey prompts.
const goConfig = getGoConfig();
@@ -67,11 +68,11 @@
const currentTime = new Date();
// Make sure the user has been idle for at least a minute.
- if (minutesBetween(lastUserAction, currentTime) < 1) {
+ if (minutesBetween(goCtx.lastUserAction, currentTime) < 1) {
setTimeout(callback, 5 * timeMinute);
return;
}
- cfg = await promptForGoplsSurvey(cfg, now);
+ cfg = await promptForGoplsSurvey(goCtx, cfg, now);
if (cfg) {
flushSurveyConfig(goplsSurveyConfig, cfg);
}
@@ -145,7 +146,11 @@
return Math.floor(Math.random() * (high - low + 1)) + low;
}
-async function promptForGoplsSurvey(cfg: GoplsSurveyConfig = {}, now: Date): Promise<GoplsSurveyConfig> {
+async function promptForGoplsSurvey(
+ goCtx: GoExtensionContext,
+ cfg: GoplsSurveyConfig = {},
+ now: Date
+): Promise<GoplsSurveyConfig> {
let selected = await vscode.window.showInformationMessage(
`Looks like you are using the Go extension for VS Code.
Could you help us improve this extension by filling out a 1-2 minute survey about your experience with it?`,
@@ -160,9 +165,10 @@
switch (selected) {
case 'Yes':
{
+ const { latestConfig } = goCtx;
cfg.lastDateAccepted = now;
cfg.prompt = true;
- const goplsEnabled = latestConfig.enabled;
+ const goplsEnabled = latestConfig?.enabled;
const usersGoplsVersion = await getLocalGoplsVersion(latestConfig);
const goV = await getGoVersion();
const goVersion = goV ? (goV.isDevel ? 'devel' : goV.format(true)) : 'na';
@@ -245,7 +251,7 @@
}
}
-export async function showSurveyConfig() {
+export async function showSurveyConfig(goCtx: GoExtensionContext) {
// TODO(rstambler): Add developer survey config.
outputChannel.appendLine('HaTs Survey Configuration');
outputChannel.appendLine(JSON.stringify(getGoplsSurveyConfig(), null, 2));
@@ -258,10 +264,10 @@
let selected = await vscode.window.showInformationMessage('Prompt for HaTS survey?', 'Yes', 'Maybe', 'No');
switch (selected) {
case 'Yes':
- promptForGoplsSurvey(getGoplsSurveyConfig(), new Date());
+ promptForGoplsSurvey(goCtx, getGoplsSurveyConfig(), new Date());
break;
case 'Maybe':
- maybePromptForGoplsSurvey();
+ maybePromptForGoplsSurvey(goCtx);
break;
default:
break;
@@ -272,7 +278,7 @@
promptForDeveloperSurvey(getDeveloperSurveyConfig(), new Date());
break;
case 'Maybe':
- maybePromptForDeveloperSurvey();
+ maybePromptForDeveloperSurvey(goCtx);
break;
default:
break;
diff --git a/src/goVulncheck.ts b/src/goVulncheck.ts
index fe173b4..29136b6 100644
--- a/src/goVulncheck.ts
+++ b/src/goVulncheck.ts
@@ -7,17 +7,16 @@
import { pathToFileURL } from 'url';
import * as vscode from 'vscode';
import { ExecuteCommandRequest } from 'vscode-languageserver-protocol';
-
-import { languageClient, serverInfo } from './language/goLanguageServer';
+import { GoExtensionContext } from './context';
export class VulncheckProvider {
static scheme = 'govulncheck';
- static setup({ subscriptions }: vscode.ExtensionContext) {
+ static setup({ subscriptions }: vscode.ExtensionContext, goCtx: GoExtensionContext) {
const channel = vscode.window.createOutputChannel('govulncheck');
const instance = new this(channel);
subscriptions.push(
vscode.commands.registerCommand('go.vulncheck.run', async () => {
- instance.run();
+ instance.run(goCtx);
})
);
return instance;
@@ -27,20 +26,20 @@
private running = false;
- async run() {
+ async run(goCtx: GoExtensionContext) {
if (this.running) {
vscode.window.showWarningMessage('another vulncheck is in progress');
return;
}
try {
this.running = true;
- await this.runInternal();
+ await this.runInternal(goCtx);
} finally {
this.running = false;
}
}
- private async runInternal() {
+ private async runInternal(goCtx: GoExtensionContext) {
const pick = await vscode.window.showQuickPick(['Current Package', 'Workspace']);
let dir, pattern: string;
const document = vscode.window.activeTextEditor?.document;
@@ -72,7 +71,7 @@
let result = '\nNo known vulnerabilities found.';
try {
- const vuln = await vulncheck(dir, pattern);
+ const vuln = await vulncheck(goCtx, dir, pattern);
if (vuln?.Vuln) {
result = vuln.Vuln.map(renderVuln).join('----------------------\n');
}
@@ -105,7 +104,12 @@
}
}
-async function vulncheck(dir: string, pattern = './...'): Promise<VulncheckReponse | undefined> {
+async function vulncheck(
+ goCtx: GoExtensionContext,
+ dir: string,
+ pattern = './...'
+): Promise<VulncheckReponse | undefined> {
+ const { languageClient, serverInfo } = goCtx;
const COMMAND = 'gopls.run_vulncheck_exp';
if (languageClient && serverInfo?.Commands?.includes(COMMAND)) {
const request = {
diff --git a/src/language/goLanguageServer.ts b/src/language/goLanguageServer.ts
index 3c8007c..e399fe6 100644
--- a/src/language/goLanguageServer.ts
+++ b/src/language/goLanguageServer.ts
@@ -38,6 +38,7 @@
import { toolExecutionEnvironment } from '../goEnv';
import { GoDocumentFormattingEditProvider, usingCustomFormatTool } from './legacy/goFormat';
import { installTools, latestToolVersion, promptForMissingTool, promptForUpdatingTool } from '../goInstallTools';
+import { GoExtensionContext } from '../context';
import {
buildDiagnosticCollection,
lintDiagnosticCollection,
@@ -55,7 +56,6 @@
getWorkspaceFolderPath,
removeDuplicateDiagnostics
} from '../util';
-import { Mutex } from '../utils/mutex';
import { getToolFromToolPath } from '../utils/pathUtils';
import WebRequest = require('web-request');
import { FoldingContext } from 'vscode';
@@ -64,7 +64,7 @@
import { maybePromptForDeveloperSurvey } from '../goDeveloperSurvey';
import { LegacyLanguageService } from './registerDefaultProviders';
-interface LanguageServerConfig {
+export interface LanguageServerConfig {
serverName: string;
path: string;
version?: { version: string; goVersion?: string };
@@ -79,48 +79,24 @@
checkForUpdates: string;
}
-// Global variables used for management of the language client.
-// They are global so that the server can be easily restarted with
-// new configurations.
-// TODO: refactor it. These can be encapsulated in a single LanguageServer class
-// that keeps track of the state of the active language server instance.
-export let languageClient: LanguageClient | undefined;
-let languageServerDisposable: vscode.Disposable | undefined;
-export let latestConfig: LanguageServerConfig;
-export let serverOutputChannel: vscode.OutputChannel | undefined;
-export let languageServerIsRunning = false;
-
-// serverInfo is the information from the server received during initialization.
-export let serverInfo: ServerInfo | undefined;
-
-interface ServerInfo {
+export interface ServerInfo {
Name: string;
Version?: string;
GoVersion?: string;
Commands?: string[];
}
-let legacyLanguageService: LegacyLanguageService | undefined;
-
-const languageServerStartMutex = new Mutex();
-
-let serverTraceChannel: vscode.OutputChannel;
-let crashCount = 0;
-
-// Some metrics for automated issue reports:
-let restartHistory: Restart[] = [];
-
-export function updateRestartHistory(reason: RestartReason, enabled: boolean) {
+export function updateRestartHistory(goCtx: GoExtensionContext, reason: RestartReason, enabled: boolean) {
// Keep the history limited to 10 elements.
- while (restartHistory.length > 10) {
- restartHistory = restartHistory.slice(1);
+ while (goCtx.restartHistory.length > 10) {
+ goCtx.restartHistory = goCtx.restartHistory.slice(1);
}
- restartHistory.push(new Restart(reason, new Date(), enabled));
+ goCtx.restartHistory.push(new Restart(reason, new Date(), enabled));
}
-function formatRestartHistory(): string {
+function formatRestartHistory(goCtx: GoExtensionContext): string {
const result: string[] = [];
- for (const restart of restartHistory) {
+ for (const restart of goCtx.restartHistory) {
result.push(`${restart.timestamp.toUTCString()}: ${restart.reason} (enabled: ${restart.enabled})`);
}
return result.join('\n');
@@ -128,7 +104,7 @@
export type RestartReason = 'activation' | 'manual' | 'config change' | 'installation';
-class Restart {
+export class Restart {
reason: RestartReason;
timestamp: Date;
enabled: boolean;
@@ -144,13 +120,13 @@
// server.
let restartCommand: vscode.Disposable;
-// lastUserAction is the time of the last user-triggered change.
-// A user-triggered change is a didOpen, didChange, didSave, or didClose event.
-export let lastUserAction: Date = new Date();
-
// startLanguageServerWithFallback starts the language server, if enabled,
// or falls back to the default language providers.
-export async function startLanguageServerWithFallback(ctx: vscode.ExtensionContext, reason: RestartReason) {
+export async function startLanguageServerWithFallback(
+ ctx: vscode.ExtensionContext,
+ goCtx: GoExtensionContext,
+ reason: RestartReason
+) {
for (const folder of vscode.workspace.workspaceFolders || []) {
switch (folder.uri.scheme) {
case 'vsls':
@@ -177,12 +153,12 @@
const goConfig = getGoConfig();
const cfg = buildLanguageServerConfig(goConfig);
- updateRestartHistory(reason, cfg.enabled);
+ updateRestartHistory(goCtx, reason, cfg.enabled);
// We have some extra prompts for gopls users and for people who have opted
// out of gopls.
if (reason === 'activation') {
- scheduleGoplsSuggestions();
+ scheduleGoplsSuggestions(goCtx);
}
// If the language server is gopls, we enable a few additional features.
@@ -197,18 +173,18 @@
}
}
}
- const unlock = await languageServerStartMutex.lock();
+ const unlock = await goCtx.languageServerStartMutex.lock();
try {
- const started = await startLanguageServer(ctx, cfg);
+ const started = await startLanguageServer(ctx, goCtx, cfg);
// If the server has been disabled, or failed to start,
// fall back to the default providers, while making sure not to
// re-register any providers.
- if (!started && !legacyLanguageService) {
- legacyLanguageService = new LegacyLanguageService(ctx);
- ctx.subscriptions.push(legacyLanguageService);
+ if (!started && !goCtx.legacyLanguageService) {
+ goCtx.legacyLanguageService = new LegacyLanguageService(ctx);
+ ctx.subscriptions.push(goCtx.legacyLanguageService);
}
- languageServerIsRunning = started;
+ goCtx.languageServerIsRunning = started;
vscode.commands.executeCommand('setContext', 'go.goplsIsRunning', started);
updateLanguageServerIconGoStatusBar(started, goConfig['useLanguageServer'] === true);
} finally {
@@ -220,7 +196,7 @@
// suggestions. We check user's gopls versions once per day to prompt users to
// update to the latest version. We also check if we should prompt users to
// fill out the survey.
-function scheduleGoplsSuggestions() {
+function scheduleGoplsSuggestions(goCtx: GoExtensionContext) {
if (extensionInfo.isInCloudIDE) {
return;
}
@@ -277,15 +253,15 @@
if (!foundGo) {
return;
}
- maybePromptForGoplsSurvey();
- maybePromptForDeveloperSurvey();
+ maybePromptForGoplsSurvey(goCtx);
+ maybePromptForDeveloperSurvey(goCtx);
};
setTimeout(update, 10 * timeMinute);
setTimeout(survey, 30 * timeMinute);
}
// Ask users to fill out opt-out survey.
-export async function promptAboutGoplsOptOut() {
+export async function promptAboutGoplsOptOut(goCtx: GoExtensionContext) {
// Check if the configuration is set in the workspace.
const useLanguageServer = getGoConfig().inspect('useLanguageServer');
const workspace = useLanguageServer?.workspaceFolderValue === false || useLanguageServer?.workspaceValue === false;
@@ -301,6 +277,7 @@
}
cfg.lastDatePrompted = new Date();
await promptForGoplsOptOutSurvey(
+ goCtx,
cfg,
"It looks like you've disabled the Go language server. Would you be willing to tell us why you've disabled it, so that we can improve it?"
);
@@ -310,12 +287,16 @@
flushGoplsOptOutConfig(cfg, workspace);
}
-async function promptForGoplsOptOutSurvey(cfg: GoplsOptOutConfig, msg: string): Promise<GoplsOptOutConfig> {
+async function promptForGoplsOptOutSurvey(
+ goCtx: GoExtensionContext,
+ cfg: GoplsOptOutConfig,
+ msg: string
+): Promise<GoplsOptOutConfig> {
const s = await vscode.window.showInformationMessage(msg, { title: 'Yes' }, { title: 'No' });
if (!s) {
return cfg;
}
- const localGoplsVersion = await getLocalGoplsVersion(latestConfig);
+ const localGoplsVersion = await getLocalGoplsVersion(goCtx.latestConfig);
const goplsVersion = localGoplsVersion?.version || 'na';
const goV = await getGoVersion();
let goVersion = 'na';
@@ -355,12 +336,17 @@
updateGlobalState(goplsOptOutConfigKey, JSON.stringify(cfg));
};
-async function startLanguageServer(ctx: vscode.ExtensionContext, config: LanguageServerConfig): Promise<boolean> {
+async function startLanguageServer(
+ ctx: vscode.ExtensionContext,
+ goCtx: GoExtensionContext,
+ config: LanguageServerConfig
+): Promise<boolean> {
// If the client has already been started, make sure to clear existing
// diagnostics and stop it.
+ const { languageClient: client, languageServerDisposable } = goCtx;
let cleanStop = true;
- if (languageClient) {
- cleanStop = await stopLanguageClient(languageClient);
+ if (client) {
+ cleanStop = await stopLanguageClient(goCtx);
if (languageServerDisposable) {
languageServerDisposable.dispose();
}
@@ -369,12 +355,12 @@
// Check if we should recreate the language client.
// This may be necessary if the user has changed settings
// in their config, or previous session wasn't stopped cleanly.
- if (!cleanStop || !deepEqual(latestConfig, config)) {
+ if (!cleanStop || !deepEqual(goCtx.latestConfig, config)) {
// Track the latest config used to start the language server,
// and rebuild the language client.
- latestConfig = config;
- languageClient = await buildLanguageClient(buildLanguageClientOption(config));
- crashCount = 0;
+ goCtx.latestConfig = config;
+ goCtx.languageClient = await buildLanguageClient(goCtx, buildLanguageClientOption(goCtx, config));
+ goCtx.crashCount = 0;
}
// If the user has not enabled the language server, return early.
@@ -387,6 +373,7 @@
if (!restartCommand) {
restartCommand = vscode.commands.registerCommand('go.languageserver.restart', async () => {
await suggestGoplsIssueReport(
+ goCtx,
"Looks like you're about to manually restart the language server.",
errorKind.manualRestart
);
@@ -398,15 +385,15 @@
// Before starting the language server, make sure to deregister any
// currently registered language providers.
- legacyLanguageService?.dispose();
- legacyLanguageService = undefined;
+ goCtx.legacyLanguageService?.dispose();
+ goCtx.legacyLanguageService = undefined;
- languageServerDisposable = languageClient?.start();
+ goCtx.languageServerDisposable = goCtx.languageClient?.start();
languageServerDisposable && ctx.subscriptions.push(languageServerDisposable);
- await languageClient?.onReady();
- serverInfo = toServerInfo(languageClient?.initializeResult);
+ await goCtx.languageClient?.onReady();
+ goCtx.serverInfo = toServerInfo(goCtx.languageClient?.initializeResult);
- console.log(`Server: ${JSON.stringify(serverInfo, null, 2)}`);
+ console.log(`Server: ${JSON.stringify(goCtx.serverInfo, null, 2)}`);
return true;
}
@@ -419,7 +406,8 @@
};
// exported for testing.
-export async function stopLanguageClient(c: LanguageClient): Promise<boolean> {
+export async function stopLanguageClient(goCtx: GoExtensionContext): Promise<boolean> {
+ const c = goCtx.languageClient;
if (!c) return false;
if (c.diagnostics) {
@@ -471,20 +459,20 @@
// buildLanguageClientOption returns the default, extra configuration
// used in building a new LanguageClient instance. Options specified
// in LanguageServerConfig
-function buildLanguageClientOption(cfg: LanguageServerConfig): BuildLanguageClientOption {
+function buildLanguageClientOption(goCtx: GoExtensionContext, cfg: LanguageServerConfig): BuildLanguageClientOption {
// Reuse the same output channel for each instance of the server.
if (cfg.enabled) {
- if (!serverOutputChannel) {
- serverOutputChannel = vscode.window.createOutputChannel(cfg.serverName + ' (server)');
+ if (!goCtx.serverOutputChannel) {
+ goCtx.serverOutputChannel = vscode.window.createOutputChannel(cfg.serverName + ' (server)');
}
- if (!serverTraceChannel) {
- serverTraceChannel = vscode.window.createOutputChannel(cfg.serverName);
+ if (!goCtx.serverTraceChannel) {
+ goCtx.serverTraceChannel = vscode.window.createOutputChannel(cfg.serverName);
}
}
return Object.assign(
{
- outputChannel: serverOutputChannel,
- traceOutputChannel: serverTraceChannel
+ outputChannel: goCtx.serverOutputChannel,
+ traceOutputChannel: goCtx.serverTraceChannel
},
cfg
);
@@ -492,7 +480,10 @@
// buildLanguageClient returns a language client built using the given language server config.
// The returned language client need to be started before use.
-export async function buildLanguageClient(cfg: BuildLanguageClientOption): Promise<LanguageClient | undefined> {
+export async function buildLanguageClient(
+ goCtx: GoExtensionContext,
+ cfg: BuildLanguageClientOption
+): Promise<LanguageClient | undefined> {
if (!cfg.enabled) {
return Promise.resolve(undefined);
}
@@ -532,6 +523,7 @@
`The language server is not able to serve any features. Initialization failed: ${error}. `
);
suggestGoplsIssueReport(
+ goCtx,
'The gopls server failed to initialize',
errorKind.initializationFailure,
error
@@ -551,11 +543,12 @@
},
closed: (): CloseAction => {
// Allow 5 crashes before shutdown.
- crashCount++;
- if (crashCount < 5) {
+ goCtx.crashCount++;
+ if (goCtx.crashCount < 5) {
return CloseAction.Restart;
}
suggestGoplsIssueReport(
+ goCtx,
'The connection to gopls has been closed. The gopls server may have crashed.',
errorKind.crash
);
@@ -572,7 +565,7 @@
'Show Trace'
);
if (answer === 'Show Trace') {
- serverOutputChannel?.show();
+ goCtx.serverOutputChannel?.show();
}
return null;
}
@@ -699,19 +692,19 @@
// Keep track of the last file change in order to not prompt
// user if they are actively working.
didOpen: (e, next) => {
- lastUserAction = new Date();
+ goCtx.lastUserAction = new Date();
next(e);
},
didChange: (e, next) => {
- lastUserAction = new Date();
+ goCtx.lastUserAction = new Date();
next(e);
},
didClose: (e, next) => {
- lastUserAction = new Date();
+ goCtx.lastUserAction = new Date();
next(e);
},
didSave: (e, next) => {
- lastUserAction = new Date();
+ goCtx.lastUserAction = new Date();
next(e);
},
workspace: {
@@ -883,7 +876,7 @@
];
}
-export async function watchLanguageServerConfiguration(e: vscode.ConfigurationChangeEvent) {
+export async function watchLanguageServerConfiguration(goCtx: GoExtensionContext, e: vscode.ConfigurationChangeEvent) {
if (!e.affectsConfiguration('go')) {
return;
}
@@ -901,7 +894,7 @@
}
if (e.affectsConfiguration('go.useLanguageServer') && getGoConfig()['useLanguageServer'] === false) {
- promptAboutGoplsOptOut();
+ promptAboutGoplsOptOut(goCtx);
}
}
@@ -1009,9 +1002,12 @@
export async function shouldUpdateLanguageServer(
tool: Tool,
- cfg: LanguageServerConfig,
+ cfg?: LanguageServerConfig,
mustCheck?: boolean
): Promise<semver.SemVer | null | undefined> {
+ if (!cfg) {
+ return null;
+ }
// Only support updating gopls for now.
if (tool.name !== 'gopls' || (!mustCheck && (cfg.checkForUpdates === 'off' || extensionInfo.isInCloudIDE))) {
return null;
@@ -1171,7 +1167,7 @@
// `gopls version` command.
//
// If this command has already been executed, it returns the saved result.
-export const getLocalGoplsVersion = async (cfg: LanguageServerConfig) => {
+export const getLocalGoplsVersion = async (cfg?: LanguageServerConfig) => {
if (!cfg) {
return null;
}
@@ -1290,6 +1286,7 @@
// suggestGoplsIssueReport prompts users to file an issue with gopls.
async function suggestGoplsIssueReport(
+ goCtx: GoExtensionContext,
msg: string,
reason: errorKind,
initializationError?: WebRequest.ResponseError<InitializeError>
@@ -1303,7 +1300,7 @@
// just prompt them to update, not file an issue.
const tool = getTool('gopls');
if (tool) {
- const versionToUpdate = await shouldUpdateLanguageServer(tool, latestConfig, true);
+ const versionToUpdate = await shouldUpdateLanguageServer(tool, goCtx.latestConfig, true);
if (versionToUpdate) {
promptForUpdatingTool(tool.name, versionToUpdate, true);
return;
@@ -1311,9 +1308,9 @@
}
// Show the user the output channel content to alert them to the issue.
- serverOutputChannel?.show();
+ goCtx.serverOutputChannel?.show();
- if (latestConfig.serverName !== 'gopls') {
+ if (goCtx.latestConfig?.serverName !== 'gopls') {
return;
}
const promptForIssueOnGoplsRestartKey = 'promptForIssueOnGoplsRestart';
@@ -1334,7 +1331,7 @@
}
}
- const { sanitizedLog, failureReason } = await collectGoplsLog();
+ const { sanitizedLog, failureReason } = await collectGoplsLog(goCtx);
// If the user has invalid values for "go.languageServerFlags", we may get
// this error. Prompt them to double check their flags.
@@ -1380,9 +1377,9 @@
break;
}
// Get the user's version in case the update prompt above failed.
- const usersGoplsVersion = await getLocalGoplsVersion(latestConfig);
+ const usersGoplsVersion = await getLocalGoplsVersion(goCtx.latestConfig);
const goVersion = await getGoVersion();
- const settings = latestConfig.flags.join(' ');
+ const settings = goCtx.latestConfig.flags.join(' ');
const title = `gopls: automated issue report (${errKind})`;
const goplsLog = sanitizedLog
? `<pre>${sanitizedLog}</pre>`
@@ -1399,14 +1396,14 @@
const body = `
gopls version: ${usersGoplsVersion?.version} (${usersGoplsVersion?.goVersion})
gopls flags: ${settings}
-update flags: ${latestConfig.checkForUpdates}
+update flags: ${goCtx.latestConfig.checkForUpdates}
extension version: ${extensionInfo.version}
go version: ${goVersion?.format(true)}
environment: ${extensionInfo.appName} ${process.platform}
initialization error: ${initializationError}
issue timestamp: ${now.toUTCString()}
restart history:
-${formatRestartHistory()}
+${formatRestartHistory(goCtx)}
ATTENTION: PLEASE PROVIDE THE DETAILS REQUESTED BELOW.
@@ -1441,13 +1438,13 @@
}
}
-export function showServerOutputChannel() {
- if (!languageServerIsRunning) {
+export function showServerOutputChannel(goCtx: GoExtensionContext) {
+ if (!goCtx.languageServerIsRunning) {
vscode.window.showInformationMessage('gopls is not running');
return;
}
// likely show() is asynchronous, despite the documentation
- serverOutputChannel?.show();
+ goCtx.serverOutputChannel?.show();
let found: vscode.TextDocument | undefined;
for (const doc of vscode.workspace.textDocuments) {
if (doc.fileName.indexOf('extension-output-') !== -1) {
@@ -1473,8 +1470,8 @@
return new Promise((resolve) => setTimeout(resolve, ms));
}
-async function collectGoplsLog(): Promise<{ sanitizedLog?: string; failureReason?: string }> {
- serverOutputChannel?.show();
+async function collectGoplsLog(goCtx: GoExtensionContext): Promise<{ sanitizedLog?: string; failureReason?: string }> {
+ goCtx.serverOutputChannel?.show();
// Find the logs in the output channel. There is no way to read
// an output channel directly, but we can find the open text
// document, since we just surfaced the output channel to the user.
diff --git a/src/language/legacy/goOutline.ts b/src/language/legacy/goOutline.ts
index 6c7e162..6552955 100644
--- a/src/language/legacy/goOutline.ts
+++ b/src/language/legacy/goOutline.ts
@@ -12,7 +12,7 @@
import { getGoConfig } from '../../config';
import { toolExecutionEnvironment } from '../../goEnv';
import { promptForMissingTool, promptForUpdatingTool } from '../../goInstallTools';
-import { languageClient, serverInfo } from '../goLanguageServer';
+import { goCtx } from '../../goMain';
import { getBinPath, getFileArchive, makeMemoizedByteOffsetConverter } from '../../util';
import { killProcess } from '../../utils/processUtils';
@@ -207,6 +207,7 @@
this.includeImports = gotoSymbolConfig ? gotoSymbolConfig['includeImports'] : false;
}
+ const { languageClient, serverInfo } = goCtx;
// TODO(suzmue): Check the commands available instead of the version.
if (languageClient && serverInfo?.Commands?.includes(GOPLS_LIST_IMPORTS)) {
const symbols: vscode.DocumentSymbol[] | undefined = await vscode.commands.executeCommand(
@@ -278,6 +279,7 @@
}
async function listImports(document: vscode.TextDocument): Promise<{ Path: string; Name: string }[]> {
+ const { languageClient } = goCtx;
const uri = languageClient?.code2ProtocolConverter.asTextDocumentIdentifier(document).uri;
const params: ExecuteCommandParams = {
command: GOPLS_LIST_IMPORTS,
diff --git a/src/util.ts b/src/util.ts
index 91d6707..af4548b 100644
--- a/src/util.ts
+++ b/src/util.ts
@@ -15,8 +15,7 @@
import { getGoConfig } from './config';
import { extensionId } from './const';
import { toolExecutionEnvironment } from './goEnv';
-import { languageClient } from './language/goLanguageServer';
-import { buildDiagnosticCollection, lintDiagnosticCollection, vetDiagnosticCollection } from './goMain';
+import { buildDiagnosticCollection, goCtx, lintDiagnosticCollection, vetDiagnosticCollection } from './goMain';
import { getCurrentPackage } from './goModules';
import { outputChannel } from './goStatus';
import { getFromWorkspaceState } from './stateUtils';
@@ -885,6 +884,7 @@
// If there are build errors on current file, ignore the new lint/vet warnings co-inciding with them
newDiagnostics = deDupeDiagnostics(buildDiagnosticCollection.get(fileUri)!.slice(), newDiagnostics);
}
+ const { languageClient } = goCtx;
// If there are errors from the language client that are on the current file, ignore the warnings co-inciding
// with them.
if (languageClient && languageClient.diagnostics?.has(fileUri)) {
diff --git a/test/gopls/extension.test.ts b/test/gopls/extension.test.ts
index 246672c..a111fcd 100644
--- a/test/gopls/extension.test.ts
+++ b/test/gopls/extension.test.ts
@@ -16,6 +16,8 @@
} from '../../src/language/goLanguageServer';
import sinon = require('sinon');
import { getGoVersion, GoVersion } from '../../src/util';
+import { Mutex } from '../../src/utils/mutex';
+import { GoExtensionContext } from '../../src/context';
// FakeOutputChannel is a fake output channel used to buffer
// the output of the tested language client in an in-memory
@@ -92,6 +94,12 @@
}
public async setup(filePath: string) {
+ const goCtx: GoExtensionContext = {
+ lastUserAction: new Date(),
+ crashCount: 0,
+ restartHistory: [],
+ languageServerStartMutex: new Mutex()
+ };
// file path to open.
this.fakeOutputChannel = new FakeOutputChannel();
const pkgLoadingDone = this.onMessageInTrace('Finished loading packages.', 60_000);
@@ -104,7 +112,7 @@
});
const cfg: BuildLanguageClientOption = buildLanguageServerConfig(goConfig);
cfg.outputChannel = this.fakeOutputChannel; // inject our fake output channel.
- this.languageClient = await buildLanguageClient(cfg);
+ this.languageClient = await buildLanguageClient(goCtx, cfg);
if (!this.languageClient) {
throw new Error('Language client not initialized.');
}
diff --git a/test/gopls/survey.test.ts b/test/gopls/survey.test.ts
index 0d9c169..128e616 100644
--- a/test/gopls/survey.test.ts
+++ b/test/gopls/survey.test.ts
@@ -9,6 +9,8 @@
import goLanguageServer = require('../../src/language/goLanguageServer');
import goSurvey = require('../../src/goSurvey');
import goDeveloperSurvey = require('../../src/goDeveloperSurvey');
+import { Mutex } from '../../src/utils/mutex';
+import { GoExtensionContext } from '../../src/context';
suite('gopls survey tests', () => {
test('prompt for survey', () => {
@@ -218,12 +220,18 @@
testCases.map(async ([testConfig, choice, wantCount], i) => {
test(`opt out: ${i}`, async () => {
+ const goCtx: GoExtensionContext = {
+ lastUserAction: new Date(),
+ crashCount: 0,
+ restartHistory: [],
+ languageServerStartMutex: new Mutex()
+ };
const stub = sandbox.stub(vscode.window, 'showInformationMessage').resolves({ title: choice });
const getGoplsOptOutConfigStub = sandbox.stub(goLanguageServer, 'getGoplsOptOutConfig').returns(testConfig);
const flushGoplsOptOutConfigStub = sandbox.stub(goLanguageServer, 'flushGoplsOptOutConfig');
sandbox.stub(vscode.env, 'openExternal').resolves(true);
- await goLanguageServer.promptAboutGoplsOptOut();
+ await goLanguageServer.promptAboutGoplsOptOut(goCtx);
assert.strictEqual(stub.callCount, wantCount, 'unexpected call count');
sandbox.assert.called(getGoplsOptOutConfigStub);
sandbox.assert.calledOnce(flushGoplsOptOutConfigStub);
diff --git a/test/integration/codelens.test.ts b/test/integration/codelens.test.ts
index 10ecaab..31500ef 100644
--- a/test/integration/codelens.test.ts
+++ b/test/integration/codelens.test.ts
@@ -12,9 +12,11 @@
import vscode = require('vscode');
import { getGoConfig } from '../../src/config';
import { updateGoVarsFromConfig } from '../../src/goInstallTools';
+import { GoExtensionContext } from '../../src/context';
import { GoRunTestCodeLensProvider } from '../../src/goRunTestCodelens';
import { subTestAtCursor } from '../../src/goTest';
import { getCurrentGoPath, getGoVersion } from '../../src/util';
+import { Mutex } from '../../src/utils/mutex';
suite('Code lenses for testing and benchmarking', function () {
this.timeout(20000);
@@ -31,7 +33,13 @@
const codeLensProvider = new GoRunTestCodeLensProvider();
suiteSetup(async () => {
- await updateGoVarsFromConfig();
+ const goCtx: GoExtensionContext = {
+ lastUserAction: new Date(),
+ crashCount: 0,
+ restartHistory: [],
+ languageServerStartMutex: new Mutex()
+ };
+ await updateGoVarsFromConfig(goCtx);
gopath = getCurrentGoPath();
if (!gopath) {
diff --git a/test/integration/coverage.test.ts b/test/integration/coverage.test.ts
index 42c598f..fbbaf65 100644
--- a/test/integration/coverage.test.ts
+++ b/test/integration/coverage.test.ts
@@ -13,6 +13,8 @@
import path = require('path');
import sinon = require('sinon');
import vscode = require('vscode');
+import { Mutex } from '../../src/utils/mutex';
+import { GoExtensionContext } from '../../src/context';
// The ideal test would check that each open editor containing a file with coverage
// information is displayed correctly. We cannot see the applied decorations, so the
@@ -25,7 +27,13 @@
let coverFilePath: string;
suiteSetup(async () => {
- await updateGoVarsFromConfig();
+ const goCtx: GoExtensionContext = {
+ lastUserAction: new Date(),
+ crashCount: 0,
+ restartHistory: [],
+ languageServerStartMutex: new Mutex()
+ };
+ await updateGoVarsFromConfig(goCtx);
// Set up the test fixtures.
fixtureSourcePath = path.join(__dirname, '..', '..', '..', 'test', 'testdata', 'coverage');
diff --git a/test/integration/extension.test.ts b/test/integration/extension.test.ts
index 00c72e5..574e911 100644
--- a/test/integration/extension.test.ts
+++ b/test/integration/extension.test.ts
@@ -49,6 +49,8 @@
} from '../../src/util';
import cp = require('child_process');
import os = require('os');
+import { GoExtensionContext } from '../../src/context';
+import { Mutex } from '../../src/utils/mutex';
const testAll = (isModuleMode: boolean) => {
const dummyCancellationSource = new vscode.CancellationTokenSource();
@@ -68,7 +70,13 @@
previousEnv = Object.assign({}, process.env);
process.env.GO111MODULE = isModuleMode ? 'on' : 'off';
- await updateGoVarsFromConfig();
+ const goCtx: GoExtensionContext = {
+ lastUserAction: new Date(),
+ crashCount: 0,
+ restartHistory: [],
+ languageServerStartMutex: new Mutex()
+ };
+ await updateGoVarsFromConfig(goCtx);
gopath = getCurrentGoPath();
if (!gopath) {
diff --git a/test/integration/goDebugConfiguration.test.ts b/test/integration/goDebugConfiguration.test.ts
index 97aa335..98b5a24 100644
--- a/test/integration/goDebugConfiguration.test.ts
+++ b/test/integration/goDebugConfiguration.test.ts
@@ -14,6 +14,8 @@
import goEnv = require('../../src/goEnv');
import { MockCfg } from '../mocks/MockCfg';
import { extensionId } from '../../src/const';
+import { GoExtensionContext } from '../../src/context';
+import { Mutex } from '../../src/utils/mutex';
suite('Debug Environment Variable Merge Test', () => {
const debugConfigProvider = new GoDebugConfigurationProvider();
@@ -23,7 +25,13 @@
const filePath = path.join(fixtureSourcePath, 'baseTest', 'test.go');
suiteSetup(async () => {
- await updateGoVarsFromConfig();
+ const goCtx: GoExtensionContext = {
+ lastUserAction: new Date(),
+ crashCount: 0,
+ restartHistory: [],
+ languageServerStartMutex: new Mutex()
+ };
+ await updateGoVarsFromConfig(goCtx);
await vscode.workspace.openTextDocument(vscode.Uri.file(filePath));
});
diff --git a/test/integration/statusbar.test.ts b/test/integration/statusbar.test.ts
index e8e8804..bf97017 100644
--- a/test/integration/statusbar.test.ts
+++ b/test/integration/statusbar.test.ts
@@ -26,11 +26,19 @@
import { MockMemento } from '../mocks/MockMemento';
import ourutil = require('../../src/util');
+import { GoExtensionContext } from '../../src/context';
import { setGOROOTEnvVar } from '../../src/goMain';
+import { Mutex } from '../../src/utils/mutex';
describe('#initGoStatusBar()', function () {
this.beforeAll(async () => {
- await updateGoVarsFromConfig(); // should initialize the status bar.
+ const goCtx: GoExtensionContext = {
+ lastUserAction: new Date(),
+ crashCount: 0,
+ restartHistory: [],
+ languageServerStartMutex: new Mutex()
+ };
+ await updateGoVarsFromConfig(goCtx); // should initialize the status bar.
});
this.afterAll(() => {