Skip to content

Commit ddc8268

Browse files
committed
extension/src: use full path mode when running go test
The fullpath mode is added in go 1.21 and the vscode-go is supporting the last three minor Go versions (1.23.0+ as of 2025-09). If the user is beyond the support, the extension will send a notification asking user to upgrade. In case user does not want to upgrade, set "-test.fullpath=false" to setting "go.testFlags" will fall back to the original behavior. Fix #3853 Change-Id: I06b723b715651ea0bf98ae62797917af7b1c74b2 Reviewed-on: https://go-review.googlesource.com/c/vscode-go/+/704776 Reviewed-by: Madeline Kalil <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent 6f77bbd commit ddc8268

File tree

5 files changed

+105
-73
lines changed

5 files changed

+105
-73
lines changed

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,19 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/).
55

66
## Unreleased
77

8+
### Important
9+
10+
* To ensure the extension remains fully compatible and stable, the required
11+
minimum Go version remains Go 1.23. A new notification will now be sent to help
12+
users running older versions upgrade to Go 1.23+.
13+
14+
### Fixes
15+
16+
* Corrected an issue where clicking on a failing test in the Test Explorer would
17+
open a non-existent Go file (golang/vscode-go#3853). This occurred when the test
18+
entry point (e.g., .../foo_test.go) was in a different directory than the file
19+
where the failure actually occurred (e.g., .../bar/bar_test.go).
20+
821
## v0.51.0 (prerelease)
922

1023
Date: 2025-09-04

extension/src/goEnvironmentStatus.ts

Lines changed: 71 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import moment = require('moment');
1313
import os = require('os');
1414
import path = require('path');
1515
import { promisify } from 'util';
16+
import semverCoerce from 'semver/functions/coerce';
1617
import { getGoConfig, extensionInfo } from './config';
1718
import { toolInstallationEnvironment } from './goEnv';
1819
import { addGoStatus, goEnvStatusbarItem, outputChannel, removeGoStatus } from './goStatus';
@@ -549,7 +550,12 @@ export async function getLatestGoVersions(): Promise<GoEnvironmentOption[]> {
549550
}
550551

551552
const STATUS_BAR_ITEM_NAME = 'Go Update Notification';
552-
const dismissedGoVersionUpdatesKey = 'dismissedGoVersionUpdates';
553+
554+
/**
555+
* Key for the global state that tracks Go versions for which the user has
556+
* explicitly dismissed the upgrade notification.
557+
*/
558+
const DISMISSED_GO_VERSION_KEY = 'dismissedGoVersionUpdates';
553559

554560
export async function offerToInstallLatestGoVersion(ctx: Pick<vscode.ExtensionContext, 'subscriptions'>) {
555561
if (extensionInfo.isInCloudIDE) {
@@ -564,83 +570,96 @@ export async function offerToInstallLatestGoVersion(ctx: Pick<vscode.ExtensionCo
564570
return;
565571
}
566572

567-
let options = await getLatestGoVersions();
573+
let latestVersions = await getLatestGoVersions();
574+
575+
const currentVersion = await getGoVersion();
576+
577+
// The official support for vscode-go is last three minor versions of Go.
578+
// Try to start with last four minor versions.
579+
let minimumVersion = semverCoerce(latestVersions[0].label);
580+
if (minimumVersion) {
581+
minimumVersion.minor = minimumVersion.minor - 3;
582+
minimumVersion.patch = 0;
583+
}
584+
585+
const download = {
586+
title: 'Download',
587+
async command() {
588+
await vscode.env.openExternal(vscode.Uri.parse('https://go.dev/dl/'));
589+
}
590+
};
591+
592+
// Popup if the Go version is beyond support.
593+
if (minimumVersion && currentVersion.lt(minimumVersion.format())) {
594+
let text = `The minimum supported Go version is ${minimumVersion.format()}. Please update your Go to ensure the extension functions correctly. You are currently using ${formatGoVersion(
595+
currentVersion
596+
)}.`;
597+
vscode.window.showInformationMessage(text, download).then((selection) => {
598+
selection?.command();
599+
});
600+
}
568601

569602
// Filter out Go versions the user has already dismissed.
570-
let dismissedOptions: GoEnvironmentOption[];
571-
dismissedOptions = await getFromGlobalState(dismissedGoVersionUpdatesKey);
572-
if (dismissedOptions) {
573-
options = options.filter((version) => !dismissedOptions.find((x) => x.label === version.label));
603+
const dismissedVersions: GoEnvironmentOption[] = await getFromGlobalState(DISMISSED_GO_VERSION_KEY);
604+
if (dismissedVersions) {
605+
latestVersions = latestVersions.filter((version) => !dismissedVersions.find((x) => x.label === version.label));
574606
}
575607

576-
// Compare to current go version.
577-
const currentVersion = await getGoVersion();
608+
// Filter out Go versions below the current go versions.
578609
if (currentVersion) {
579-
options = options.filter((version) => currentVersion.lt(version.label));
610+
latestVersions = latestVersions.filter((version) => currentVersion.lt(version.label));
580611
}
581612

582613
// Notify user that there is a newer version of Go available.
583-
if (options.length > 0) {
584-
const versionsText = options.map((x) => x.label).join(', ');
585-
const statusBarItem = addGoStatus(STATUS_BAR_ITEM_NAME);
586-
statusBarItem.name = STATUS_BAR_ITEM_NAME;
587-
statusBarItem.text = 'New Go version is available';
588-
statusBarItem.detail = versionsText;
589-
statusBarItem.command = {
590-
title: 'Upgrade',
591-
command: 'go.promptforgoinstall',
592-
arguments: [options],
593-
tooltip: 'Upgrade or silence notification'
594-
};
595-
// TODO: Error level is more visible. Consider to make it configurable?
596-
statusBarItem.severity = vscode.LanguageStatusSeverity.Warning;
597-
614+
if (latestVersions.length > 0) {
598615
ctx.subscriptions.push(
599616
vscode.commands.registerCommand('go.promptforgoinstall', () => {
600-
const download = {
601-
title: 'Download',
602-
async command() {
603-
await vscode.env.openExternal(vscode.Uri.parse('https://go.dev/dl/'));
604-
}
605-
};
606-
607617
const neverAgain = {
608618
title: "Don't Show Again",
609619
async command() {
610620
// Mark these versions as seen.
611-
dismissedOptions = await getFromGlobalState(dismissedGoVersionUpdatesKey);
612-
if (!dismissedOptions) {
613-
dismissedOptions = [];
621+
let dismissedVersions: GoEnvironmentOption[] = await getFromGlobalState(
622+
DISMISSED_GO_VERSION_KEY
623+
);
624+
if (!dismissedVersions) {
625+
dismissedVersions = [];
614626
}
615-
options.forEach((version) => {
616-
dismissedOptions.push(version);
627+
latestVersions.forEach((version) => {
628+
dismissedVersions.push(version);
617629
});
618-
await updateGlobalState(dismissedGoVersionUpdatesKey, dismissedOptions);
630+
await updateGlobalState(DISMISSED_GO_VERSION_KEY, dismissedVersions);
619631
}
620632
};
621633

622-
let versionsText: string;
623-
if (options.length > 1) {
624-
versionsText = `${options
634+
let text: string;
635+
if (latestVersions.length > 1) {
636+
text = `${latestVersions
625637
.map((x) => x.label)
626638
.reduce((prev, next) => {
627639
return prev + ' and ' + next;
628640
})} are available`;
629641
} else {
630-
versionsText = `${options[0].label} is available`;
642+
text = `${latestVersions[0].label} is available.`;
631643
}
632-
633-
vscode.window
634-
.showInformationMessage(
635-
`${versionsText}. You are currently using ${formatGoVersion(currentVersion)}.`,
636-
download,
637-
neverAgain
638-
)
639-
.then((selection) => {
640-
selection?.command();
641-
removeGoStatus(STATUS_BAR_ITEM_NAME);
642-
});
644+
text = text + ` You are currently using ${formatGoVersion(currentVersion)}.`;
645+
vscode.window.showInformationMessage(text, download, neverAgain).then((selection) => {
646+
selection?.command();
647+
removeGoStatus(STATUS_BAR_ITEM_NAME);
648+
});
643649
})
644650
);
651+
652+
const statusBarItem = addGoStatus(STATUS_BAR_ITEM_NAME);
653+
statusBarItem.name = STATUS_BAR_ITEM_NAME;
654+
statusBarItem.text = 'New Go version is available';
655+
statusBarItem.detail = latestVersions.map((x) => x.label).join(', ');
656+
statusBarItem.command = {
657+
title: 'Upgrade',
658+
command: 'go.promptforgoinstall',
659+
arguments: [latestVersions],
660+
tooltip: 'Upgrade or silence notification'
661+
};
662+
// TODO: Error level is more visible. Consider to make it configurable?
663+
statusBarItem.severity = vscode.LanguageStatusSeverity.Warning;
645664
}
646665
}

extension/src/goMain.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ import { GO_MODE } from './goMode';
4545
import { GO111MODULE, goModInit } from './goModules';
4646
import { playgroundCommand } from './goPlayground';
4747
import { GoRunTestCodeLensProvider } from './goRunTestCodelens';
48-
import { disposeGoStatusBar, expandGoStatusBar, outputChannel, updateGoStatusBar } from './goStatus';
48+
import { disposeGoStatusBar, expandGoStatusBar, updateGoStatusBar } from './goStatus';
4949

5050
import { vetCode } from './goVet';
5151
import {
@@ -75,7 +75,6 @@ import { toggleVulncheckCommandFactory } from './goVulncheck';
7575
import { GoTaskProvider } from './goTaskProvider';
7676
import { setTelemetryEnvVars, activationLatency, telemetryReporter } from './goTelemetry';
7777
import { experiments } from './experimental';
78-
import { allToolsInformation } from './goToolsInformation';
7978

8079
const goCtx: GoExtensionContext = {};
8180

extension/src/testUtils.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -544,7 +544,8 @@ export function computeTestCommand(
544544
tmpCoverPath?: string; // coverage file path if coverage info is necessary.
545545
addJSONFlag: boolean | undefined; // true if we add extra -json flag for stream processing.
546546
} {
547-
const args: Array<string> = ['test'];
547+
// By default, enable full path mode to address golang/vscode-go#3853.
548+
const args: Array<string> = ['test', '-test.fullpath=true'];
548549
// user-specified flags
549550
const argsFlagIdx = testconfig.flags?.indexOf('-args') ?? -1;
550551
const userFlags = argsFlagIdx < 0 ? testconfig.flags : testconfig.flags.slice(0, argsFlagIdx);

extension/test/integration/test.test.ts

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -42,67 +42,67 @@ suite('Test Go Test Args', () => {
4242

4343
test('default config', () => {
4444
runTest({
45-
expectedArgs: 'test -timeout 30s ./...',
46-
expectedOutArgs: 'test -timeout 30s ./...'
45+
expectedArgs: 'test -test.fullpath=true -timeout 30s ./...',
46+
expectedOutArgs: 'test -test.fullpath=true -timeout 30s ./...'
4747
});
4848
});
4949
test('user flag [-v] enables -json flag', () => {
5050
runTest({
51-
expectedArgs: 'test -timeout 30s -json ./... -v',
52-
expectedOutArgs: 'test -timeout 30s ./... -v',
51+
expectedArgs: 'test -test.fullpath=true -timeout 30s -json ./... -v',
52+
expectedOutArgs: 'test -test.fullpath=true -timeout 30s ./... -v',
5353
flags: ['-v']
5454
});
5555
});
5656
test('user flag [-json -v] prevents -json flag addition', () => {
5757
runTest({
58-
expectedArgs: 'test -timeout 30s ./... -json -v',
59-
expectedOutArgs: 'test -timeout 30s ./... -json -v',
58+
expectedArgs: 'test -test.fullpath=true -timeout 30s ./... -json -v',
59+
expectedOutArgs: 'test -test.fullpath=true -timeout 30s ./... -json -v',
6060
flags: ['-json', '-v']
6161
});
6262
});
6363
test('user flag [-args] does not crash', () => {
6464
runTest({
65-
expectedArgs: 'test -timeout 30s ./... -args',
66-
expectedOutArgs: 'test -timeout 30s ./... -args',
65+
expectedArgs: 'test -test.fullpath=true -timeout 30s ./... -args',
66+
expectedOutArgs: 'test -test.fullpath=true -timeout 30s ./... -args',
6767
flags: ['-args']
6868
});
6969
});
7070
test('user flag [-args -v] does not enable -json flag', () => {
7171
runTest({
72-
expectedArgs: 'test -timeout 30s ./... -args -v',
73-
expectedOutArgs: 'test -timeout 30s ./... -args -v',
72+
expectedArgs: 'test -test.fullpath=true -timeout 30s ./... -args -v',
73+
expectedOutArgs: 'test -test.fullpath=true -timeout 30s ./... -args -v',
7474
flags: ['-args', '-v']
7575
});
7676
});
7777
test('specifying functions adds -run flags', () => {
7878
runTest({
79-
expectedArgs: 'test -timeout 30s -run ^(TestA|TestB)$ ./...',
80-
expectedOutArgs: 'test -timeout 30s -run ^(TestA|TestB)$ ./...',
79+
expectedArgs: 'test -test.fullpath=true -timeout 30s -run ^(TestA|TestB)$ ./...',
80+
expectedOutArgs: 'test -test.fullpath=true -timeout 30s -run ^(TestA|TestB)$ ./...',
8181
functions: ['TestA', 'TestB']
8282
});
8383
});
8484
test('functions & benchmark adds -bench flags and skips timeout', () => {
8585
runTest({
86-
expectedArgs: 'test -benchmem -run=^$ -bench ^(TestA|TestB)$ ./...',
87-
expectedOutArgs: 'test -benchmem -run=^$ -bench ^(TestA|TestB)$ ./...',
86+
expectedArgs: 'test -test.fullpath=true -benchmem -run=^$ -bench ^(TestA|TestB)$ ./...',
87+
expectedOutArgs: 'test -test.fullpath=true -benchmem -run=^$ -bench ^(TestA|TestB)$ ./...',
8888
functions: ['TestA', 'TestB'],
8989
isBenchmark: true
9090
});
9191
});
9292
test('user -run flag is ignored when functions are provided', () => {
9393
runTest({
94-
expectedArgs: 'test -timeout 30s -run ^(TestA|TestB)$ ./...',
95-
expectedOutArgs: 'test -timeout 30s -run ^(TestA|TestB)$ ./...',
94+
expectedArgs: 'test -test.fullpath=true -timeout 30s -run ^(TestA|TestB)$ ./...',
95+
expectedOutArgs: 'test -test.fullpath=true -timeout 30s -run ^(TestA|TestB)$ ./...',
9696
functions: ['TestA', 'TestB'],
9797
flags: ['-run', 'TestC']
9898
});
9999
});
100100
test('use -testify.m for methods', () => {
101101
runTest({
102102
expectedArgs:
103-
'test -timeout 30s -run ^TestExampleTestSuite$ -testify.m ^(TestExample|TestAnotherExample)$ ./...',
103+
'test -test.fullpath=true -timeout 30s -run ^TestExampleTestSuite$ -testify.m ^(TestExample|TestAnotherExample)$ ./...',
104104
expectedOutArgs:
105-
'test -timeout 30s -run ^TestExampleTestSuite$ -testify.m ^(TestExample|TestAnotherExample)$ ./...',
105+
'test -test.fullpath=true -timeout 30s -run ^TestExampleTestSuite$ -testify.m ^(TestExample|TestAnotherExample)$ ./...',
106106
functions: [
107107
'(*ExampleTestSuite).TestExample',
108108
'(*ExampleTestSuite).TestAnotherExample',

0 commit comments

Comments
 (0)