From 4316a961ee8a5ad7c9c664adca9b26318bf14ead Mon Sep 17 00:00:00 2001 From: "Hana (Hyang-Ah) Kim" Date: Thu, 2 Nov 2023 13:51:57 -0400 Subject: [PATCH] src/language/goLanguageServer: improve suggestGoplsIssueReport The extension runs suggestGoplsIssueReport when it observes the language server client crashes. It prompts the user and collects useful information from settings, configuration, and the LSP server output channel ("gopls (server)") where stderr and LSP log messages are logged, populates a github issue template when the user agrees. This change improves the log collection and sanitization. * Incorrect version info and timestamp - previously they were computed after the user chooses "Yes" on the prompt. Usually, there is a delay between the problem occurs and the user notices the popup. Often, vscode hides the prompt window! It's possible that a new gopls or extension version was installed and restarted in between. This CL makes the suggestGoplsIssueReport accepts the configuration used when starting the crashed gopls session, and computes the issue timestamp before prompting. Moreover, we also compute the gopls version when the configuration object is built. Previously, it was lazily evaluated to avoid excessive file stats and `gopls version` process runs. In this CL, we remove unnecessary buildLanguageServerConfig calls - the latest config is cached in `goCtx.latestCfg`. One side-effect of this change is `buildLanguageServerConfig` is now async to run `gopls version`. * Gopls's crash info is in `gopls (server)` output channel. collectGoplsLog attempted to collect the data in a hacky way by iterating all open documents and picking the first one that looks like our log. Unfortunately, this doesn't work when there are multiple extensions with output channels. Fix this bug - recent versions of vscode now use file names that include the channel name, so we can pin point the right output channel doc. * The extension may trigger multiple gopls restarts back to back because there are currently multiple vantage points for checking for gopls update asynchronously. Such successive restarts may be unclean and the lsp client lib classifies them as crashes. The new session may be already up and running. This CL makes suggestGoplsIssueReport check gopls versions (what's used in the currently crashed session and what's the latest config the extension saw) and prompt only if they are same. It would be nice if we can centralize gopls install/upgrade decision making and reduce the chance of successive, unnecessary gopls restarts. But that is a major change and can be a separate project. We also learned a couple of new crash log patterns. Integrate the followings in the log scrubbing logic. * log.Fatal - "filename.go:line ...." * LSP 3.17 client library changed the initialization error log text. That explains the increased in the number of empty reports after we updated our dependency. This change also embeds `gopls stats -anon` output. That may reveal issues in the workspace setup. For a large project, gopls stats may take a while. Limit the execution to 60sec. While we are here, we also simplify the periodic gopls update check (scheduleGoplsSuggestions). That will remove another buildLanguageServerConfig call. Fixes golang/vscode-go#984 Fixes golang/vscode-go#2690 Change-Id: Ib8aa2abbd5f0c812605ced13c9c93b8aa3bb94fd Reviewed-on: https://go-review.googlesource.com/c/vscode-go/+/539415 Auto-Submit: Hyang-Ah Hana Kim Commit-Queue: Hyang-Ah Hana Kim TryBot-Result: kokoro Reviewed-by: Robert Findley Reviewed-by: Suzy Mueller Run-TryBot: Hyang-Ah Hana Kim --- src/commands/startLanguageServer.ts | 3 +- src/goCheck.ts | 4 +- src/goStatus.ts | 13 +-- src/language/goLanguageServer.ts | 147 ++++++++++++++++------------ src/utils/pathUtils.ts | 2 +- test/gopls/goplsTestEnv.utils.ts | 2 +- test/gopls/report.test.ts | 34 ++++--- test/integration/extension.test.ts | 4 +- 8 files changed, 117 insertions(+), 92 deletions(-) diff --git a/src/commands/startLanguageServer.ts b/src/commands/startLanguageServer.ts index 6c672fb5b9..f01d1f97c4 100644 --- a/src/commands/startLanguageServer.ts +++ b/src/commands/startLanguageServer.ts @@ -30,7 +30,7 @@ const languageServerStartMutex = new Mutex(); export const startLanguageServer: CommandFactory = (ctx, goCtx) => { return async (reason: RestartReason = RestartReason.MANUAL) => { const goConfig = getGoConfig(); - const cfg = buildLanguageServerConfig(goConfig); + const cfg = await buildLanguageServerConfig(goConfig); if (typeof reason === 'string') { updateRestartHistory(goCtx, reason, cfg.enabled); @@ -42,6 +42,7 @@ export const startLanguageServer: CommandFactory = (ctx, goCtx) => { if (reason === RestartReason.MANUAL) { await suggestGoplsIssueReport( goCtx, + cfg, "Looks like you're about to manually restart the language server.", errorKind.manualRestart ); diff --git a/src/goCheck.ts b/src/goCheck.ts index ff8113677f..c71574b820 100644 --- a/src/goCheck.ts +++ b/src/goCheck.ts @@ -11,7 +11,6 @@ import path = require('path'); import vscode = require('vscode'); import { getGoplsConfig } from './config'; import { goBuild } from './goBuild'; -import { buildLanguageServerConfig } from './language/goLanguageServer'; import { goLint } from './goLint'; import { isModSupported } from './goModules'; import { diagnosticsStatusBarItem, outputChannel } from './goStatus'; @@ -68,8 +67,7 @@ export function check( // If a user has enabled diagnostics via a language server, // then we disable running build or vet to avoid duplicate errors and warnings. - const lspConfig = buildLanguageServerConfig(goConfig); - const disableBuildAndVet = lspConfig.enabled; + const disableBuildAndVet = goConfig.get('useLanguageServer'); let testPromise: Thenable; const testConfig: TestConfig = { diff --git a/src/goStatus.ts b/src/goStatus.ts index 01b12240f3..6ce338b514 100644 --- a/src/goStatus.ts +++ b/src/goStatus.ts @@ -11,7 +11,6 @@ import vscode = require('vscode'); import vscodeUri = require('vscode-uri'); import { getGoConfig } from './config'; import { formatGoVersion, GoEnvironmentOption, terminalCreationListener } from './goEnvironmentStatus'; -import { buildLanguageServerConfig, getLocalGoplsVersion } from './language/goLanguageServer'; import { isGoFile } from './goMode'; import { isModSupported, runGoEnv } from './goModules'; import { allToolsInformation } from './goToolsInformation'; @@ -61,14 +60,16 @@ export const expandGoStatusBar: CommandFactory = (ctx, goCtx) => async () => { { label: 'Choose Go Environment' } ]; - // Get the gopls configuration + const cfg = goCtx.latestConfig; + // Get the gopls configuration. const goConfig = getGoConfig(); - const cfg = buildLanguageServerConfig(goConfig); - if (languageServerIsRunning && cfg.serverName === 'gopls') { - const goplsVersion = await getLocalGoplsVersion(cfg); + const goplsIsRunning = languageServerIsRunning && cfg && cfg.serverName === 'gopls'; + if (goplsIsRunning) { + const goplsVersion = cfg.version; options.push({ label: `${languageServerIcon}Open 'gopls' trace`, description: `${goplsVersion?.version}` }); } - if (!languageServerIsRunning && !cfg.serverName && goConfig['useLanguageServer'] === true) { + // In case gopls still need to be installed, cfg.serverName will be empty. + if (!goplsIsRunning && goConfig.get('useLanguageServer') === true && cfg?.serverName === '') { options.push({ label: 'Install Go Language Server', description: `${languageServerErrorIcon}'gopls' is required but missing` diff --git a/src/language/goLanguageServer.ts b/src/language/goLanguageServer.ts index 60ee6ed27b..ea2c3c2b16 100644 --- a/src/language/goLanguageServer.ts +++ b/src/language/goLanguageServer.ts @@ -158,9 +158,6 @@ export function scheduleGoplsSuggestions(goCtx: GoExtensionContext) { return; } // Some helper functions. - const usingGopls = (cfg: LanguageServerConfig): boolean => { - return cfg.enabled && cfg.serverName === 'gopls'; - }; const usingGo = (): boolean => { return vscode.workspace.textDocuments.some((doc) => doc.languageId === 'go'); }; @@ -187,20 +184,11 @@ export function scheduleGoplsSuggestions(goCtx: GoExtensionContext) { }; const update = async () => { setTimeout(update, timeDay); - - let cfg = buildLanguageServerConfig(getGoConfig()); - if (!usingGopls(cfg)) { - // This shouldn't happen, but if the user has a non-gopls language - // server enabled, we shouldn't prompt them to change. - if (cfg.serverName !== '' && cfg.serverName !== 'gopls') { - return; - } - // Check if the language server has now been enabled, and if so, - // it will be installed below. - cfg = buildLanguageServerConfig(getGoConfig()); - if (!cfg.enabled) { - return; - } + const cfg = goCtx.latestConfig; + // trigger periodic update check only if the user is already using gopls. + // Otherwise, let's check again tomorrow. + if (!cfg || !cfg.enabled || cfg.serverName !== 'gopls') { + return; } await installGopls(cfg); }; @@ -300,14 +288,6 @@ export const flushGoplsOptOutConfig = (cfg: GoplsOptOutConfig, workspace: boolea updateGlobalState(goplsOptOutConfigKey, JSON.stringify(cfg)); }; -const race = function (promise: Promise, timeoutInMilliseconds: number) { - let token: NodeJS.Timeout; - const timeout = new Promise((resolve, reject) => { - token = setTimeout(() => reject('timeout'), timeoutInMilliseconds); - }); - return Promise.race([promise, timeout]).then(() => clearTimeout(token)); -}; - // exported for testing. export async function stopLanguageClient(goCtx: GoExtensionContext) { const c = goCtx.languageClient; @@ -322,10 +302,8 @@ export async function stopLanguageClient(goCtx: GoExtensionContext) { // LanguageClient.stop may hang if the language server // crashes during shutdown before responding to the // shutdown request. Enforce client-side timeout. - // TODO(hyangah): replace with the new LSP client API that supports timeout - // and remove this. try { - await race(c.stop(), 2000); + c.stop(2000); } catch (e) { c.outputChannel?.appendLine(`Failed to stop client: ${e}`); } @@ -416,6 +394,7 @@ export async function buildLanguageClient( goCtx: GoExtensionContext, cfg: BuildLanguageClientOption ): Promise { + await getLocalGoplsVersion(cfg); // populate and cache cfg.version const goplsWorkspaceConfig = await adjustGoplsWorkspaceConfiguration(cfg, getGoplsConfig(), 'gopls', undefined); const documentSelector = [ @@ -435,7 +414,7 @@ export async function buildLanguageClient( const pendingVulncheckProgressToken = new Map(); const onDidChangeVulncheckResultEmitter = new vscode.EventEmitter(); - + // cfg is captured by closures for later use during error report. const c = new GoLanguageClient( 'go', // id cfg.serverName, // name e.g. gopls @@ -470,6 +449,7 @@ export async function buildLanguageClient( }; } return { + message: '', // suppresses error popups action: ErrorAction.Shutdown }; }, @@ -477,6 +457,7 @@ export async function buildLanguageClient( if (initializationError !== undefined) { suggestGoplsIssueReport( goCtx, + cfg, 'The gopls server failed to initialize.', errorKind.initializationFailure, initializationError @@ -484,7 +465,7 @@ export async function buildLanguageClient( initializationError = undefined; // In case of initialization failure, do not try to restart. return { - message: 'The gopls server failed to initialize.', + message: '', // suppresses error popups - there will be other popups. :-( action: CloseAction.DoNotRestart }; } @@ -500,11 +481,13 @@ export async function buildLanguageClient( } suggestGoplsIssueReport( goCtx, + cfg, 'The connection to gopls has been closed. The gopls server may have crashed.', errorKind.crash ); updateLanguageServerIconGoStatusBar(false, true); return { + message: '', // suppresses error popups - there will be other popups. action: CloseAction.DoNotRestart }; } @@ -968,16 +951,16 @@ export async function watchLanguageServerConfiguration(goCtx: GoExtensionContext } } -export function buildLanguageServerConfig(goConfig: vscode.WorkspaceConfiguration): LanguageServerConfig { +export async function buildLanguageServerConfig( + goConfig: vscode.WorkspaceConfiguration +): Promise { let formatter: GoDocumentFormattingEditProvider | undefined; if (usingCustomFormatTool(goConfig)) { formatter = new GoDocumentFormattingEditProvider(); } const cfg: LanguageServerConfig = { - serverName: '', + serverName: '', // remain empty if gopls binary can't be found. path: '', - version: undefined, // compute version lazily - modtime: undefined, enabled: goConfig['useLanguageServer'] === true, flags: goConfig['languageServerFlags'] || [], features: { @@ -1015,7 +998,7 @@ Please try reinstalling it.`); return cfg; } cfg.modtime = stats.mtime; - + cfg.version = await getLocalGoplsVersion(cfg); return cfg; } @@ -1208,13 +1191,13 @@ interface GoplsVersionOutput { // If this command has already been executed, it returns the saved result. export const getLocalGoplsVersion = async (cfg?: LanguageServerConfig) => { if (!cfg) { - return null; + return; } if (cfg.version) { return cfg.version; } if (cfg.path === '') { - return null; + return; } const env = toolExecutionEnvironment(); const cwd = getWorkspaceFolderPath(); @@ -1240,7 +1223,7 @@ export const getLocalGoplsVersion = async (cfg?: LanguageServerConfig) => { } catch (e) { // The "gopls version" command is not supported, or something else went wrong. // TODO: Should we propagate this error? - return null; + return; } const lines = output.trim().split('\n'); @@ -1248,17 +1231,17 @@ export const getLocalGoplsVersion = async (cfg?: LanguageServerConfig) => { case 0: // No results, should update. // Worth doing anything here? - return null; + return; case 1: // Built in $GOPATH mode. Should update. // TODO: Should we check the Go version here? // Do we even allow users to enable gopls if their Go version is too low? - return null; + return; case 2: // We might actually have a parseable version. break; default: - return null; + return; } // The second line should be the sum line. @@ -1277,7 +1260,7 @@ export const getLocalGoplsVersion = async (cfg?: LanguageServerConfig) => { // const split = moduleVersion.trim().split('@'); if (split.length < 2) { - return null; + return; } // The version comes after the @ symbol: // @@ -1326,15 +1309,26 @@ export enum errorKind { // suggestGoplsIssueReport prompts users to file an issue with gopls. export async function suggestGoplsIssueReport( goCtx: GoExtensionContext, + cfg: LanguageServerConfig, // config used when starting this gopls. msg: string, reason: errorKind, initializationError?: WebRequest.ResponseError ) { + const issueTime = new Date(); + // Don't prompt users who manually restart to file issues until gopls/v1.0. if (reason === errorKind.manualRestart) { return; } + // cfg is the config used when starting this crashed gopls instance, while + // goCtx.latestConfig is the config used by the latest gopls instance. + // They may be different if gopls upgrade occurred in between. + // Let's not report issue yet if they don't match. + if (JSON.stringify(goCtx.latestConfig?.version) !== JSON.stringify(cfg.version)) { + return; + } + // The user may have an outdated version of gopls, in which case we should // just prompt them to update, not file an issue. const tool = getTool('gopls'); @@ -1378,15 +1372,16 @@ export async function suggestGoplsIssueReport( if (failureReason === GoplsFailureModes.INCORRECT_COMMAND_USAGE) { const languageServerFlags = getGoConfig()['languageServerFlags'] as string[]; if (languageServerFlags && languageServerFlags.length > 0) { - selected = await vscode.window.showInformationMessage( + selected = await vscode.window.showErrorMessage( `The extension was unable to start the language server. You may have an invalid value in your "go.languageServerFlags" setting. -It is currently set to [${languageServerFlags}]. Please correct the setting by navigating to Preferences -> Settings.`, - 'Open settings', +It is currently set to [${languageServerFlags}]. +Please correct the setting.`, + 'Open Settings', 'I need more help.' ); switch (selected) { - case 'Open settings': + case 'Open Settings': await vscode.commands.executeCommand('workbench.action.openSettings', 'go.languageServerFlags'); return; case 'I need more help': @@ -1395,7 +1390,8 @@ It is currently set to [${languageServerFlags}]. Please correct the setting by n } } } - selected = await vscode.window.showInformationMessage( + const showMessage = sanitizedLog ? vscode.window.showWarningMessage : vscode.window.showInformationMessage; + selected = await showMessage( `${msg} Would you like to report a gopls issue on GitHub? You will be asked to provide additional information and logs, so PLEASE READ THE CONTENT IN YOUR BROWSER.`, 'Yes', @@ -1415,11 +1411,9 @@ You will be asked to provide additional information and logs, so PLEASE READ THE errKind = 'initialization'; break; } - // Get the user's version in case the update prompt above failed. - const usersGoplsVersion = await getLocalGoplsVersion(goCtx.latestConfig); - const goVersion = await getGoVersion(); const settings = goCtx.latestConfig.flags.join(' '); const title = `gopls: automated issue report (${errKind})`; + const goplsStats = await getGoplsStats(goCtx.latestConfig?.path); const goplsLog = sanitizedLog ? `
${sanitizedLog}
` : `Please attach the stack trace from the crash. @@ -1430,17 +1424,15 @@ Please copy the stack trace and error messages from that window and paste it in Failed to auto-collect gopls trace: ${failureReason}. `; - const now = new Date(); const body = ` -gopls version: ${usersGoplsVersion?.version} (${usersGoplsVersion?.goVersion}) +gopls version: ${cfg.version?.version}/${cfg.version?.goVersion} gopls flags: ${settings} -update flags: ${goCtx.latestConfig.checkForUpdates} +update flags: ${cfg.checkForUpdates} extension version: ${extensionInfo.version} -go version: ${goVersion?.format(true)} environment: ${extensionInfo.appName} ${process.platform} initialization error: ${initializationError} -issue timestamp: ${now.toUTCString()} +issue timestamp: ${issueTime.toUTCString()} restart history: ${formatRestartHistory(goCtx)} @@ -1452,6 +1444,10 @@ Describe what you observed. ${goplsLog} +
gopls stats -anon +${goplsStats} +
+ OPTIONAL: If you would like to share more information, you can attach your complete gopls logs. NOTE: THESE MAY CONTAIN SENSITIVE INFORMATION ABOUT YOUR CODEBASE. @@ -1459,7 +1455,7 @@ DO NOT SHARE LOGS IF YOU ARE WORKING IN A PRIVATE REPOSITORY. `; - const url = `https://github.com/golang/vscode-go/issues/new?title=${title}&labels=upstream-tools&body=${body}`; + const url = `https://github.com/golang/vscode-go/issues/new?title=${title}&labels=automatedReport&body=${body}`; await vscode.env.openExternal(vscode.Uri.parse(url)); } break; @@ -1525,12 +1521,10 @@ async function collectGoplsLog(goCtx: GoExtensionContext): Promise<{ sanitizedLo if (doc.isDirty || doc.isClosed) { continue; } - // The document's name should look like 'extension-output-#X'. - if (doc.fileName.indexOf('extension-output-') === -1) { - continue; + if (doc.fileName.indexOf('gopls (server)') > -1) { + logs = doc.getText(); + break; } - logs = doc.getText(); - break; } if (logs) { break; @@ -1538,7 +1532,6 @@ async function collectGoplsLog(goCtx: GoExtensionContext): Promise<{ sanitizedLo // sleep a bit before the next try. The choice of the sleep time is arbitrary. await sleep((i + 1) * 100); } - return sanitizeGoplsTrace(logs); } @@ -1588,7 +1581,7 @@ export function sanitizeGoplsTrace(logs?: string): { sanitizedLog?: string; fail } return { failureReason: GoplsFailureModes.INCOMPLETE_PANIC_TRACE }; } - const initFailMsgBegin = logs.lastIndexOf('Starting client failed'); + const initFailMsgBegin = logs.lastIndexOf('gopls client:'); if (initFailMsgBegin > -1) { // client start failed. Capture up to the 'Code:' line. const initFailMsgEnd = logs.indexOf('Code: ', initFailMsgBegin); @@ -1602,9 +1595,16 @@ export function sanitizeGoplsTrace(logs?: string): { sanitizedLog?: string; fail }; } } - if (logs.lastIndexOf('Usage: gopls') > -1) { + if (logs.lastIndexOf('Usage:') > -1) { return { failureReason: GoplsFailureModes.INCORRECT_COMMAND_USAGE }; } + // Capture Fatal + // foo.go:1: the last message (caveat - we capture only the first log line) + const m = logs.match(/(^\S+\.go:\d+:.*$)/gm); + if (m && m.length > 0) { + return { sanitizedLog: m[0].toString() }; + } + return { failureReason: GoplsFailureModes.UNRECOGNIZED_CRASH_PATTERN }; } @@ -1656,3 +1656,22 @@ export function maybePromptForTelemetry(goCtx: GoExtensionContext) { }; callback(); } + +async function getGoplsStats(binpath?: string) { + if (!binpath) { + return 'gopls path unknown'; + } + const env = toolExecutionEnvironment(); + const cwd = getWorkspaceFolderPath(); + const start = new Date(); + const execFile = util.promisify(cp.execFile); + try { + const timeout = 60 * 1000; // 60sec; + const { stdout } = await execFile(binpath, ['stats', '-anon'], { env, cwd, timeout }); + return stdout; + } catch (e) { + const duration = new Date().getTime() - start.getTime(); + console.log(`gopls stats -anon failed: ${JSON.stringify(e)}`); + return `gopls stats -anon failed after running for ${duration}ms`; // e may contain user information. don't include in the report. + } +} diff --git a/src/utils/pathUtils.ts b/src/utils/pathUtils.ts index ead04ac328..ad4509db48 100644 --- a/src/utils/pathUtils.ts +++ b/src/utils/pathUtils.ts @@ -247,7 +247,7 @@ export function fixDriveCasingInWindows(pathToFix: string): string { } /** - * Returns the tool name from the given path to the tool + * Returns the tool name (executable's basename) from the given path to the tool * @param toolPath */ export function getToolFromToolPath(toolPath: string): string | undefined { diff --git a/test/gopls/goplsTestEnv.utils.ts b/test/gopls/goplsTestEnv.utils.ts index a6bc9996f6..95d2d4ef04 100644 --- a/test/gopls/goplsTestEnv.utils.ts +++ b/test/gopls/goplsTestEnv.utils.ts @@ -108,7 +108,7 @@ export class Env { if (!goConfig) { goConfig = getGoConfig(); } - const cfg: BuildLanguageClientOption = buildLanguageServerConfig( + const cfg: BuildLanguageClientOption = await buildLanguageServerConfig( Object.create(goConfig, { useLanguageServer: { value: true }, languageServerFlags: { value: ['-rpc.trace'] } // enable rpc tracing to monitor progress reports diff --git a/test/gopls/report.test.ts b/test/gopls/report.test.ts index dd121e71e6..4cabab95d4 100644 --- a/test/gopls/report.test.ts +++ b/test/gopls/report.test.ts @@ -22,8 +22,8 @@ suite('gopls issue report tests', () => { }, { name: 'initialization error message', - in: traceFromIssueVSCodeGo572, - want: sanitizedTraceFromIssuVSCodeGo572 + in: traceFromIssueVSCodeGo572LSP317, + want: sanitizedTraceFromIssueVSCodeGo572LSP317 }, { name: 'incomplete panic trace', @@ -40,8 +40,8 @@ suite('gopls issue report tests', () => { testCases.map((tc: TestCase) => { const { sanitizedLog, failureReason } = sanitizeGoplsTrace(tc.in); assert.strictEqual( - sanitizedLog, - tc.want, + JSON.stringify(sanitizedLog), + JSON.stringify(tc.want), `sanitizeGoplsTrace(${tc.name}) returned unexpected sanitizedLog result` ); assert.strictEqual( @@ -317,15 +317,21 @@ created by golang.org/x/tools/internal/jsonrpc2.AsyncHandler.func1 handler.go:100 +0x171 [Info - 12:50:26 PM] `; -const traceFromIssueVSCodeGo572 = ` - -[Error - 下午9:23:45] Starting client failed -Message: unsupported URI scheme: (gopls only supports file URIs) -Code: 0 -[Info - 下午9:23:45] 2020/08/25 21:23:45 server shutdown without initialization - +const traceFromIssueVSCodeGo572LSP317 = ` +[Error - 12:20:35 PM] Stopping server failed +Error: Client is not running and can't be stopped. It's current state is: startFailed + at GoLanguageClient.shutdown (/Users/hakim/projects/vscode-go/dist/goMain.js:21702:17) + at GoLanguageClient.stop (/Users/hakim/projects/vscode-go/dist/goMain.js:21679:21) + at GoLanguageClient.stop (/Users/hakim/projects/vscode-go/dist/goMain.js:23486:22) + at GoLanguageClient.handleConnectionError (/Users/hakim/projects/vscode-go/dist/goMain.js:21920:16) + at process.processTicksAndRejections (node:internal/process/task_queues:95:5) +[Error - 12:20:35 PM] +[Error - 12:20:35 PM] gopls client: couldn't create connection to server. + Message: Socket closed before the connection was established + Code: -32099 +Error starting language server: Error: Socket closed before the connection was established <-- this will be included in the initialization error field. `; -const sanitizedTraceFromIssuVSCodeGo572 = `Starting client failed -Message: unsupported URI scheme: (gopls only supports file URIs) -Code: 0`; +const sanitizedTraceFromIssueVSCodeGo572LSP317 = `gopls client: couldn't create connection to server. + Message: Socket closed before the connection was established + Code: -32099 `; diff --git a/test/integration/extension.test.ts b/test/integration/extension.test.ts index b6aa5f72af..ca76d4d4ac 100644 --- a/test/integration/extension.test.ts +++ b/test/integration/extension.test.ts @@ -210,7 +210,7 @@ const testAll = (isModuleMode: boolean) => { ]; // If a user has enabled diagnostics via a language server, // then we disable running build or vet to avoid duplicate errors and warnings. - const lspConfig = buildLanguageServerConfig(getGoConfig()); + const lspConfig = await buildLanguageServerConfig(getGoConfig()); const expectedBuildVetErrors = lspConfig.enabled ? [] : [{ line: 11, severity: 'error', msg: 'undefined: prin' }]; @@ -489,7 +489,7 @@ const testAll = (isModuleMode: boolean) => { }); test('Build Tags checking', async () => { - const goplsConfig = buildLanguageServerConfig(getGoConfig()); + const goplsConfig = await buildLanguageServerConfig(getGoConfig()); if (goplsConfig.enabled) { // Skip this test if gopls is enabled. Build/Vet checks this test depend on are // disabled when the language server is enabled, and gopls is not handling tags yet.