Skip to content

Commit 229bc4a

Browse files
authored
Merge branch 'master' into feature/show_var_as_doc
2 parents 5e87de9 + 85d7f0c commit 229bc4a

34 files changed

+974
-422
lines changed

CHANGELOG.md

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

88
Added menu in a debugger that will show variable in a new document with respect to special chars like `\r\n\t`
99

10+
## v0.49.1 (prerelease)
11+
12+
Date: 2025-08-21
13+
14+
This is the [pre-release version](https://code.visualstudio.com/api/working-with-extensions/publishing-extension#prerelease-extensions) of v0.50.
15+
16+
**Full Changelog**: https://github.com/golang/vscode-go/compare/v0.48.0-rc.1...v0.49.1
17+
**Milestone**: https://github.com/golang/vscode-go/issues?q=milestone%3Av0.50.0
18+
1019
## v0.49.0 (prerelease)
1120

1221
Date: 2025-07-07

docs/commands.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,15 +121,19 @@ Displays test coverage in the current package.
121121

122122
### `Go: Generate Unit Tests For Package`
123123

124-
Generates unit tests for the current package
124+
Generates unit tests for the current package using gotests
125125

126126
### `Go: Generate Unit Tests For File`
127127

128-
Generates unit tests for the current file
128+
Generates unit tests for the current file using gotests
129129

130130
### `Go: Generate Unit Tests For Function`
131131

132-
Generates unit tests for the selected function in the current file
132+
Generates unit tests for the selected function in the current file using gopls
133+
134+
### `Go: Generate Unit Tests For Function (legacy)`
135+
136+
Generates unit tests for the selected function in the current file using gotests
133137

134138
### `Go: Generate Interface Stubs`
135139

extension/package.json

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -341,17 +341,22 @@
341341
{
342342
"command": "go.test.generate.package",
343343
"title": "Go: Generate Unit Tests For Package",
344-
"description": "Generates unit tests for the current package"
344+
"description": "Generates unit tests for the current package using gotests"
345345
},
346346
{
347347
"command": "go.test.generate.file",
348348
"title": "Go: Generate Unit Tests For File",
349-
"description": "Generates unit tests for the current file"
349+
"description": "Generates unit tests for the current file using gotests"
350350
},
351351
{
352352
"command": "go.test.generate.function",
353353
"title": "Go: Generate Unit Tests For Function",
354-
"description": "Generates unit tests for the selected function in the current file"
354+
"description": "Generates unit tests for the selected function in the current file using gopls"
355+
},
356+
{
357+
"command": "go.test.generate.function.legacy",
358+
"title": "Go: Generate Unit Tests For Function (legacy)",
359+
"description": "Generates unit tests for the selected function in the current file using gotests"
355360
},
356361
{
357362
"command": "go.impl.cursor",
@@ -3496,7 +3501,7 @@
34963501
"debug/callstack/context": [
34973502
{
34983503
"command": "go.debug.toggleHideSystemGoroutines",
3499-
"when": "debugType == 'go' && callStackItemType == 'stackFrame' || (callStackItemType == 'thread' && callStackItemStopped)"
3504+
"when": "debugType == 'go' && (callStackItemType == 'stackFrame' || (callStackItemType == 'thread' && callStackItemStopped))"
35003505
}
35013506
],
35023507
"debug/variables/context": [
@@ -3552,6 +3557,11 @@
35523557
"command": "go.test.generate.function",
35533558
"group": "Go group 1"
35543559
},
3560+
{
3561+
"when": "editorTextFocus && config.go.editorContextMenuCommands.generateTestForFunction && resourceLangId == go",
3562+
"command": "go.test.generate.function.legacy",
3563+
"group": "Go group 1"
3564+
},
35553565
{
35563566
"when": "editorTextFocus && config.go.editorContextMenuCommands.generateTestForFile && resourceLangId == go",
35573567
"command": "go.test.generate.file",
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
/*---------------------------------------------------------
2+
* Copyright 2025 The Go Authors. All rights reserved.
3+
* Licensed under the MIT License. See LICENSE in the project root for license information.
4+
*--------------------------------------------------------*/
5+
6+
import * as cp from 'child_process';
7+
import * as fs from 'fs';
8+
import * as path from 'path';
9+
import * as util from 'util';
10+
import { URL } from 'url';
11+
import { getStateConfig } from '../goSurvey';
12+
import { getBinPath } from '../util';
13+
import { updateGlobalState } from '../stateUtils';
14+
import { outputChannel } from '../goStatus';
15+
16+
/**
17+
* DeveloperSurveyConfig holds the configuration for the Go Developer survey.
18+
*/
19+
export interface DeveloperSurveyConfig {
20+
/** The start date for the survey promotion. The survey will not be prompted before this date. */
21+
StartDate: Date;
22+
/** The end date for the survey promotion. The survey will not be prompted after this date. */
23+
EndDate: Date;
24+
/** The URL for the survey. */
25+
URL: string;
26+
}
27+
28+
/**
29+
* DEVELOPER_SURVEY_CONFIG_STATE_KEY is the key for the latest go developer
30+
* survey config stored in VSCode memento. It should not be changed to maintain
31+
* backward compatibility with previous extension versions.
32+
*/
33+
export const DEVELOPER_SURVEY_CONFIG_STATE_KEY = 'developerSurveyConfigState';
34+
35+
/**
36+
* DeveloperSurveyConfigState holds the most recently fetched survey
37+
* configuration, along with metadata about when it was fetched and its version.
38+
* This data is stored in the global memento to be used as a cache.
39+
*/
40+
export interface DeveloperSurveyConfigState {
41+
config: DeveloperSurveyConfig;
42+
version: string;
43+
lastDateUpdated: Date;
44+
}
45+
46+
export function getDeveloperSurveyConfigState(): DeveloperSurveyConfigState {
47+
return getStateConfig(DEVELOPER_SURVEY_CONFIG_STATE_KEY) as DeveloperSurveyConfigState;
48+
}
49+
50+
/**
51+
* getLatestDeveloperSurvey fetches the latest Go Developer Survey configuration.
52+
*
53+
* It first checks for a cached version of the survey config and returns it if it's
54+
* less than 24 hours old. Otherwise, it attempts to download the latest survey
55+
* configuration by fetching the specified Go module. If the download fails,
56+
* it falls back to returning the stale cached config if available.
57+
*
58+
* @returns A Promise that resolves to the DeveloperSurveyConfig, or undefined.
59+
*/
60+
export async function getLatestDeveloperSurvey(now: Date): Promise<DeveloperSurveyConfig | undefined> {
61+
const oldState = getDeveloperSurveyConfigState();
62+
if (oldState && oldState.config) {
63+
const SURVEY_CACHE_DURATION_MS = 24 * 60 * 60 * 1000; // 24 hours
64+
65+
if (now.getTime() - oldState.lastDateUpdated.getTime() <= SURVEY_CACHE_DURATION_MS) {
66+
outputChannel.info(`Using cached Go developer survey: ${oldState.version}`);
67+
outputChannel.info(
68+
`Survey active from ${oldState.config.StartDate.toDateString()} to ${oldState.config.EndDate.toDateString()}`
69+
);
70+
return oldState.config;
71+
}
72+
}
73+
74+
// Fetch the latest go developer survey module and flush it to momento.
75+
const res = await fetchRemoteSurveyConfig();
76+
if (!res) {
77+
if (oldState && oldState.config) {
78+
outputChannel.info(`Falling back to cached Go developer survey: ${oldState.version}`);
79+
outputChannel.info(
80+
`Survey active from ${oldState.config.StartDate.toDateString()} to ${oldState.config.EndDate.toDateString()}`
81+
);
82+
return oldState.config;
83+
} else {
84+
return undefined;
85+
}
86+
}
87+
88+
const [content, version] = res;
89+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
90+
const config = JSON.parse(content.toString(), (key: string, value: any) => {
91+
// Manually parse date fields.
92+
if (key === 'StartDate' || key === 'EndDate') {
93+
return new Date(value);
94+
}
95+
return value;
96+
}) as DeveloperSurveyConfig;
97+
98+
const newState: DeveloperSurveyConfigState = {
99+
config: config,
100+
version: version,
101+
lastDateUpdated: now
102+
};
103+
104+
// The survey URL stored in config.json is the raw survey URL. We add the
105+
// s=v (for vscode) query parameter to identify the source of the survey
106+
// respondent.
107+
const url = new URL(config.URL);
108+
url.searchParams.append('s', 'v');
109+
config.URL = url.toString();
110+
111+
updateGlobalState(DEVELOPER_SURVEY_CONFIG_STATE_KEY, JSON.stringify(newState));
112+
113+
outputChannel.info(`Using fetched Go developer survey: ${newState.version}`);
114+
outputChannel.info(
115+
`Survey active from ${newState.config.StartDate.toDateString()} to ${newState.config.EndDate.toDateString()}`
116+
);
117+
return config;
118+
}
119+
120+
/**
121+
* Fetches the latest survey config file from its Go module.
122+
* @returns A tuple containing the file content and the module version.
123+
*
124+
* This is defined as a const function expression rather than a function
125+
* declaration to allow it to be stubbed in tests. By defining it as a const,
126+
* it becomes a property on the module's exports object, which can be
127+
* replaced by test spies (e.g., using sandbox.stub).
128+
*/
129+
export const fetchRemoteSurveyConfig = async (): Promise<[string, string] | undefined> => {
130+
const SURVEY_MODULE_PATH = 'github.com/golang/vscode-go/survey';
131+
132+
outputChannel.info('Fetching latest go developer survey');
133+
const goRuntimePath = getBinPath('go');
134+
if (!goRuntimePath) {
135+
console.warn('Failed to run "go mod download" as the "go" binary cannot be found');
136+
return;
137+
}
138+
139+
const execFile = util.promisify(cp.execFile);
140+
141+
try {
142+
const { stdout } = await execFile(goRuntimePath, ['mod', 'download', '-json', `${SURVEY_MODULE_PATH}@latest`]);
143+
144+
/**
145+
* Interface for the expected JSON output from `go mod download -json`.
146+
* See https://go.dev/ref/mod#go-mod-download for details.
147+
*/
148+
interface DownloadModuleOutput {
149+
Path: string;
150+
Version: string;
151+
Dir: string;
152+
}
153+
const info = JSON.parse(stdout) as DownloadModuleOutput;
154+
return [fs.readFileSync(path.join(info.Dir, 'config.json')).toString(), info.Version];
155+
} catch (err) {
156+
outputChannel.error(
157+
`Failed to download the go developer survey module and parse "config.json": ${SURVEY_MODULE_PATH}:${err}`
158+
);
159+
return;
160+
}
161+
};

0 commit comments

Comments
 (0)