Skip to content

Commit 55e2ee9

Browse files
authored
Merge pull request #13978 from microsoft/main
Merge for 1.25.1 (pre-release)
2 parents 52620d6 + 40590bb commit 55e2ee9

File tree

14 files changed

+140
-48
lines changed

14 files changed

+140
-48
lines changed

Build/package/jobs_package_vsix.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,25 @@ parameters:
55
- name: srcDir
66
type: string
77
default: ''
8+
- name: signType
9+
type: string
10+
default: 'real'
811

912
jobs:
1013
- job: package
1114
displayName: Build ${{ parameters.vsixName }}
1215
timeoutInMinutes: 30
1316
cancelTimeoutInMinutes: 1
1417
templateContext:
18+
mb: # Enable the MicroBuild Signing toolset
19+
signing:
20+
enabled: true
21+
signType: ${{ parameters.signType }}
22+
zipSources: false
23+
${{ if eq(parameters.signType, 'real') }}:
24+
signWithProd: true
25+
featureFlags:
26+
autoBaseline: false
1527
outputs:
1628
- output: pipelineArtifact
1729
displayName: '${{ parameters.vsixName }}'

Extension/.vscodeignore

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,25 +29,25 @@ jobs/**
2929
cgmanifest.json
3030

3131
# ignore development files
32-
tsconfig.json
33-
test.tsconfig.json
34-
ui.tsconfig.json
35-
tslint.json
32+
.eslintignore
3633
.eslintrc.js
37-
webpack.config.js
38-
tscCompileList.txt
39-
gulpfile.js
4034
.gitattributes
4135
.gitignore
36+
gulpfile.js
37+
localized_string_ids.h
38+
readme.developer.md
39+
Reinstalling the Extension.md
40+
test.tsconfig.json
41+
translations_auto_pr.js
42+
tsconfig.json
43+
tslint.json
44+
tscCompileList.txt
45+
ui.tsconfig.json
46+
webpack.config.js
4247
CMakeLists.txt
4348
debugAdapters/install.lock*
4449
typings/**
4550
**/*.map
46-
import_edge_strings.js
47-
localized_string_ids.h
48-
translations_auto_pr.js
49-
readme.developer.md
50-
Reinstalling the Extension.md
5151
*.d.ts
5252

5353
# ignore i18n language files

Extension/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# C/C++ for Visual Studio Code Changelog
22

3+
## Version 1.28.1: October 6, 2025
4+
### Bug Fixes
5+
* Fix extension activation getting stuck when certain SSH config files are processed (by the SSH targets view feature). [#13966](https://github.com/microsoft/vscode-cpptools/issues/13966)
6+
* Fix document symbols randomly showing previous versions of symbols after they are modified. [#13967](https://github.com/microsoft/vscode-cpptools/issues/13967)
7+
* A potential fix for a crash.
8+
39
## Version 1.28.0: September 25, 2025
410
### Enhancements
511
* Add IntelliSense support for c23 `bool`, `true`, and `false`. [#13737](https://github.com/microsoft/vscode-cpptools/issues/13737)

Extension/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "cpptools",
33
"displayName": "C/C++",
44
"description": "C/C++ IntelliSense, debugging, and code browsing.",
5-
"version": "1.28.0-main",
5+
"version": "1.28.1-main",
66
"publisher": "ms-vscode",
77
"icon": "LanguageCCPP_color_128x.png",
88
"readme": "README.md",

Extension/src/LanguageServer/client.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1391,6 +1391,7 @@ export class DefaultClient implements Client {
13911391
}
13921392

13931393
this.copilotCompletionProvider = CopilotCompletionContextProvider.Create();
1394+
util.setProgress(util.getProgressCopilotSuccess());
13941395
this.disposables.push(this.copilotCompletionProvider);
13951396

13961397
// Listen for messages from the language server.

Extension/src/SSH/sshHosts.ts

Lines changed: 53 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -99,28 +99,64 @@ export async function getSshConfiguration(configurationPath: string, resolveIncl
9999
return config;
100100
}
101101

102-
async function resolveConfigIncludes(config: Configuration, configPath: string): Promise<void> {
103-
for (const entry of config) {
104-
if (isDirective(entry) && entry.param === 'Include') {
105-
let includePath: string = resolveHome(entry.value);
106-
if (isWindows && !!includePath.match(/^\/[a-z]:/i)) {
107-
includePath = includePath.substr(1);
108-
}
109-
110-
if (!path.isAbsolute(includePath)) {
111-
includePath = path.resolve(path.dirname(configPath), includePath);
112-
}
113-
114-
const pathsToGetFilesFrom: string[] = await globAsync(includePath);
102+
function getProcessedPathKey(filePath: string): string {
103+
const absolutePath: string = path.resolve(filePath);
104+
const normalizedPath: string = path.normalize(absolutePath);
105+
return isWindows ? normalizedPath.toLowerCase() : normalizedPath;
106+
}
115107

116-
for (const filePath of pathsToGetFilesFrom) {
117-
await getIncludedConfigFile(config, filePath);
108+
async function resolveConfigIncludes(
109+
config: Configuration,
110+
configPath: string,
111+
processedIncludePaths?: Set<string>,
112+
processedIncludeEntries?: WeakSet<ConfigurationDirective>
113+
): Promise<void> {
114+
processedIncludePaths = processedIncludePaths ?? new Set<string>();
115+
processedIncludeEntries = processedIncludeEntries ?? new WeakSet<ConfigurationDirective>();
116+
const configKey: string = getProcessedPathKey(configPath);
117+
if (processedIncludePaths.has(configKey)) {
118+
return;
119+
}
120+
processedIncludePaths.add(configKey);
121+
try {
122+
for (const entry of config) {
123+
if (isDirective(entry) && entry.param === 'Include') {
124+
// Prevent duplicate expansion of the same Include directive within a single resolution pass.
125+
if (processedIncludeEntries.has(entry)) {
126+
continue;
127+
}
128+
processedIncludeEntries.add(entry);
129+
let includePath: string = resolveHome(entry.value);
130+
if (isWindows && !!includePath.match(/^\/[a-z]:/i)) {
131+
includePath = includePath.slice(1);
132+
}
133+
134+
if (!path.isAbsolute(includePath)) {
135+
includePath = path.resolve(path.dirname(configPath), includePath);
136+
}
137+
138+
const pathsToGetFilesFrom: string[] = await globAsync(includePath);
139+
140+
for (const filePath of pathsToGetFilesFrom) {
141+
const includeKey: string = getProcessedPathKey(filePath);
142+
if (processedIncludePaths.has(includeKey)) {
143+
continue;
144+
}
145+
await getIncludedConfigFile(config, filePath, processedIncludePaths, processedIncludeEntries);
146+
}
118147
}
119148
}
149+
} finally {
150+
processedIncludePaths.delete(configKey);
120151
}
121152
}
122153

123-
async function getIncludedConfigFile(config: Configuration, includePath: string): Promise<void> {
154+
async function getIncludedConfigFile(
155+
config: Configuration,
156+
includePath: string,
157+
processedIncludePaths: Set<string>,
158+
processedIncludeEntries: WeakSet<ConfigurationDirective>
159+
): Promise<void> {
124160
let includedContents: string;
125161
try {
126162
includedContents = (await fs.readFile(includePath)).toString();
@@ -136,6 +172,7 @@ async function getIncludedConfigFile(config: Configuration, includePath: string)
136172
getSshChannel().appendLine(localize("failed.to.parse.SSH.config", "Failed to parse SSH configuration file {0}: {1}", includePath, (err as Error).message));
137173
return;
138174
}
175+
await resolveConfigIncludes(parsedIncludedContents, includePath, processedIncludePaths, processedIncludeEntries);
139176
config.push(...parsedIncludedContents);
140177
}
141178

Extension/src/common.ts

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -247,19 +247,22 @@ export function displayExtensionNotReadyPrompt(): void {
247247
// Users start with a progress of 0 and it increases as they get further along in using the tool.
248248
// This eliminates noise/problems due to re-installs, terminated installs that don't send errors,
249249
// errors followed by workarounds that lead to success, etc.
250-
const progressInstallSuccess: number = 100;
250+
const progressDebuggerStarted: number = 50;
251+
const progressDebuggerSuccess: number = 100;
251252
const progressExecutableStarted: number = 150;
253+
const progressCopilotSuccess: number = 180;
252254
const progressExecutableSuccess: number = 200;
253255
const progressParseRootSuccess: number = 300;
256+
const progressLanguageServiceDisabled: number = 400;
254257
const progressIntelliSenseNoSquiggles: number = 1000;
255258
// Might add more IntelliSense progress measurements later.
256-
// IntelliSense progress is separate from the install progress, because parse root can occur afterwards.
259+
// IntelliSense progress is separate from the activation progress, because parse root can occur afterwards.
257260

258-
const installProgressStr: string = "CPP." + packageJson.version + ".Progress";
261+
const activationProgressStr: string = "CPP." + packageJson.version + ".Progress";
259262
const intelliSenseProgressStr: string = "CPP." + packageJson.version + ".IntelliSenseProgress";
260263

261264
export function getProgress(): number {
262-
return extensionContext ? extensionContext.globalState.get<number>(installProgressStr, -1) : -1;
265+
return extensionContext ? extensionContext.globalState.get<number>(activationProgressStr, -1) : -1;
263266
}
264267

265268
export function getIntelliSenseProgress(): number {
@@ -268,15 +271,18 @@ export function getIntelliSenseProgress(): number {
268271

269272
export function setProgress(progress: number): void {
270273
if (extensionContext && getProgress() < progress) {
271-
void extensionContext.globalState.update(installProgressStr, progress);
274+
void extensionContext.globalState.update(activationProgressStr, progress);
272275
const telemetryProperties: Record<string, string> = {};
273276
let progressName: string | undefined;
274277
switch (progress) {
275-
case 0: progressName = "install started"; break;
276-
case progressInstallSuccess: progressName = "install succeeded"; break;
278+
case 0: progressName = "activation started"; break;
279+
case progressDebuggerStarted: progressName = "debugger started"; break;
280+
case progressDebuggerSuccess: progressName = "debugger succeeded"; break;
277281
case progressExecutableStarted: progressName = "executable started"; break;
282+
case progressCopilotSuccess: progressName = "copilot succeeded"; break;
278283
case progressExecutableSuccess: progressName = "executable succeeded"; break;
279284
case progressParseRootSuccess: progressName = "parse root succeeded"; break;
285+
case progressLanguageServiceDisabled: progressName = "language service disabled"; break;
280286
}
281287
if (progressName) {
282288
telemetryProperties.progress = progressName;
@@ -300,10 +306,13 @@ export function setIntelliSenseProgress(progress: number): void {
300306
}
301307
}
302308

303-
export function getProgressInstallSuccess(): number { return progressInstallSuccess; } // Download/install was successful (i.e. not blocked by component acquisition).
309+
export function getProgressDebuggerStarted(): number { return progressDebuggerStarted; } // Debugger initialization was started.
310+
export function getProgressDebuggerSuccess(): number { return progressDebuggerSuccess; } // Debugger was successfully initialized.
304311
export function getProgressExecutableStarted(): number { return progressExecutableStarted; } // The extension was activated and starting the executable was attempted.
312+
export function getProgressCopilotSuccess(): number { return progressCopilotSuccess; } // Copilot activation was successful.
305313
export function getProgressExecutableSuccess(): number { return progressExecutableSuccess; } // Starting the exe was successful (i.e. not blocked by 32-bit or glibc < 2.18 on Linux)
306314
export function getProgressParseRootSuccess(): number { return progressParseRootSuccess; } // Parse root was successful (i.e. not blocked by processing taking too long).
315+
export function getProgressLanguageServiceDisabled(): number { return progressLanguageServiceDisabled; } // The user disabled the language service.
307316
export function getProgressIntelliSenseNoSquiggles(): number { return progressIntelliSenseNoSquiggles; } // IntelliSense was successful and the user got no squiggles.
308317

309318
export function isUri(input: any): input is vscode.Uri {

Extension/src/main.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ export async function activate(context: vscode.ExtensionContext): Promise<CppToo
4242
});
4343

4444
util.setExtensionContext(context);
45-
Telemetry.activate();
4645
util.setProgress(0);
46+
Telemetry.activate();
4747

4848
// Register a protocol handler to serve localized versions of the schema for c_cpp_properties.json
4949
class SchemaProvider implements vscode.TextDocumentContentProvider {
@@ -63,7 +63,9 @@ export async function activate(context: vscode.ExtensionContext): Promise<CppToo
6363
vscode.workspace.registerTextDocumentContentProvider('cpptools-schema', instrument(new SchemaProvider()));
6464

6565
// Initialize the DebuggerExtension and register the related commands and providers.
66+
util.setProgress(util.getProgressDebuggerStarted());
6667
await DebuggerExtension.initialize(context);
68+
util.setProgress(util.getProgressDebuggerSuccess());
6769

6870
const info: PlatformInformation = await PlatformInformation.GetPlatformInformation();
6971
sendTelemetry(info);
@@ -161,6 +163,7 @@ export async function activate(context: vscode.ExtensionContext): Promise<CppToo
161163
// The check here for isIntelliSenseEngineDisabled avoids logging
162164
// the message on old Macs that we've already displayed a warning for.
163165
log(localize("intellisense.disabled", "intelliSenseEngine is disabled"));
166+
util.setProgress(util.getProgressLanguageServiceDisabled());
164167
}
165168

166169
// Send an instrumentation message upon completing activation.

ExtensionPack/CHANGELOG.md

Lines changed: 0 additions & 7 deletions
This file was deleted.

ExtensionPack/package-lock.json

Lines changed: 16 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)