Skip to content

Commit 5077edf

Browse files
authored
Merge pull request #11886 from microsoft/main
Merge for 1.19.2 (2nd time)
2 parents f38926f + 3f1e851 commit 5077edf

File tree

5 files changed

+161
-24
lines changed

5 files changed

+161
-24
lines changed

Extension/CHANGELOG.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
# C/C++ for Visual Studio Code Changelog
22

3-
## Version 1.19.2: January 17, 2024
3+
## Version 1.19.2: January 22, 2024
44
### Enhancements
55
* Implement progressive population of IntelliSense results. [#7759](https://github.com/microsoft/vscode-cpptools/issues/7759)
6+
* Improve memory efficiency by using token parsing in the 'Add #include' feature. [#11515](https://github.com/microsoft/vscode-cpptools/issues/11515)
67
* Improve the types supported for the 'Add #include' code action.
78
* Various performance improvements.
89

@@ -16,6 +17,7 @@
1617
* Fix German code analysis translations. [PR #11845](https://github.com/microsoft/vscode-cpptools/pull/11845)
1718
* Thank you for the contribution [@Sir2B (Tobias Obermayer)](https://github.com/Sir2B)
1819
* Fix an EACCES error when using include wildcards with system includes. [#11833](https://github.com/microsoft/vscode-cpptools/issues/11833)
20+
* Fix IntelliSense passes occurring while a user is typing, not honoring the `C_Cpp.intelliSenseUpdateDelay` setting.
1921
* Fix a call hierarchy bug leading to use of header-only TU's unnecessarily.
2022
* Fix a bug that could lead to missing TU source file candidates.
2123
* Fix a "random" IntelliSense crash during completion.

Extension/package.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -5811,17 +5811,17 @@
58115811
},
58125812
"configurationDefaults": {
58135813
"[cpp]": {
5814-
"editor.wordBasedSuggestions": false,
5814+
"editor.wordBasedSuggestions": "off",
58155815
"editor.suggest.insertMode": "replace",
58165816
"editor.semanticHighlighting.enabled": true
58175817
},
58185818
"[cuda-cpp]": {
5819-
"editor.wordBasedSuggestions": false,
5819+
"editor.wordBasedSuggestions": "off",
58205820
"editor.suggest.insertMode": "replace",
58215821
"editor.semanticHighlighting.enabled": true
58225822
},
58235823
"[c]": {
5824-
"editor.wordBasedSuggestions": false,
5824+
"editor.wordBasedSuggestions": "off",
58255825
"editor.suggest.insertMode": "replace",
58265826
"editor.semanticHighlighting.enabled": true
58275827
}

Extension/src/LanguageServer/client.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ import {
5353
import { Location, TextEdit, WorkspaceEdit } from './commonTypes';
5454
import * as configs from './configurations';
5555
import { DataBinding } from './dataBinding';
56-
import { CppSourceStr, clients, configPrefix, updateLanguageConfigurations } from './extension';
56+
import { CppSourceStr, clients, configPrefix, updateLanguageConfigurations, watchForCrashes } from './extension';
5757
import { LocalizeStringParams, getLocaleId, getLocalizedString } from './localization';
5858
import { PersistentFolderState, PersistentWorkspaceState } from './persistentState';
5959
import { createProtocolFilter } from './protocolFilter';
@@ -536,7 +536,7 @@ interface DidChangeActiveEditorParams {
536536
}
537537

538538
// Requests
539-
const InitializationRequest: RequestType<CppInitializationParams, void, void> = new RequestType<CppInitializationParams, void, void>('cpptools/initialize');
539+
const InitializationRequest: RequestType<CppInitializationParams, string, void> = new RequestType<CppInitializationParams, string, void>('cpptools/initialize');
540540
const QueryCompilerDefaultsRequest: RequestType<QueryDefaultCompilerParams, configs.CompilerDefaults, void> = new RequestType<QueryDefaultCompilerParams, configs.CompilerDefaults, void>('cpptools/queryCompilerDefaults');
541541
const QueryTranslationUnitSourceRequest: RequestType<QueryTranslationUnitSourceParams, QueryTranslationUnitSourceResult, void> = new RequestType<QueryTranslationUnitSourceParams, QueryTranslationUnitSourceResult, void>('cpptools/queryTranslationUnitSource');
542542
const SwitchHeaderSourceRequest: RequestType<SwitchHeaderSourceParams, string, void> = new RequestType<SwitchHeaderSourceParams, string, void>('cpptools/didSwitchHeaderSource');
@@ -1572,7 +1572,7 @@ export class DefaultClient implements Client {
15721572
// Move initialization to a separate message, so we can see log output from it.
15731573
// A request is used in order to wait for completion and ensure that no subsequent
15741574
// higher priority message may be processed before the Initialization request.
1575-
await languageClient.sendRequest(InitializationRequest, cppInitializationParams);
1575+
watchForCrashes(await languageClient.sendRequest(InitializationRequest, cppInitializationParams));
15761576
}
15771577

15781578
public async sendDidChangeSettings(): Promise<void> {

Extension/src/LanguageServer/extension.ts

+126-9
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import * as vscode from 'vscode';
1414
import { Range } from 'vscode-languageclient';
1515
import * as nls from 'vscode-nls';
1616
import { TargetPopulation } from 'vscode-tas-client';
17+
import * as which from 'which';
1718
import { logAndReturn } from '../Utility/Async/returns';
1819
import * as util from '../common';
1920
import { PlatformInformation } from '../platform';
@@ -922,8 +923,8 @@ function reportMacCrashes(): void {
922923
const crashObject: Record<string, string> = {};
923924
if (err?.code) {
924925
// If the directory isn't there, we have a problem...
925-
crashObject["fs.stat: err.code"] = err.code;
926-
telemetry.logLanguageServerEvent("MacCrash", crashObject, undefined);
926+
crashObject["errCode"] = err.code;
927+
telemetry.logLanguageServerEvent("MacCrash", crashObject);
927928
return;
928929
}
929930

@@ -959,17 +960,64 @@ function reportMacCrashes(): void {
959960
}
960961
}
961962

962-
let previousMacCrashData: string;
963-
let previousMacCrashCount: number = 0;
963+
export function watchForCrashes(crashDirectory: string): void {
964+
if (process.platform !== "win32") {
965+
prevCrashFile = "";
966+
fs.stat(crashDirectory, (err) => {
967+
const crashObject: Record<string, string> = {};
968+
if (err?.code) {
969+
// If the directory isn't there, we have a problem...
970+
crashObject["errCode"] = err.code;
971+
telemetry.logLanguageServerEvent("CppCrash", crashObject);
972+
return;
973+
}
964974

965-
function logMacCrashTelemetry(data: string): void {
975+
// vscode.workspace.createFileSystemWatcher only works in workspace folders.
976+
try {
977+
fs.watch(crashDirectory, (event, filename) => {
978+
if (event !== "rename") {
979+
return;
980+
}
981+
if (!filename || filename === prevCrashFile) {
982+
return;
983+
}
984+
prevCrashFile = filename;
985+
if (!filename.startsWith("cpptools")) {
986+
return;
987+
}
988+
// Wait 5 seconds to allow time for the crash log to finish being written.
989+
setTimeout(() => {
990+
fs.readFile(path.resolve(crashDirectory, filename), 'utf8', (err, data) => {
991+
void handleCrashFileRead(crashDirectory, filename, err, data);
992+
});
993+
}, 5000);
994+
});
995+
} catch (e) {
996+
// The file watcher limit is hit (may not be possible on Mac, but just in case).
997+
}
998+
});
999+
}
1000+
}
1001+
1002+
let previousCrashData: string;
1003+
let previousCrashCount: number = 0;
1004+
1005+
function logCrashTelemetry(data: string, type: string): void {
9661006
const crashObject: Record<string, string> = {};
9671007
const crashCountObject: Record<string, number> = {};
9681008
crashObject.CrashingThreadCallStack = data;
969-
previousMacCrashCount = data === previousMacCrashData ? previousMacCrashCount + 1 : 0;
970-
previousMacCrashData = data;
971-
crashCountObject.CrashCount = previousMacCrashCount;
972-
telemetry.logLanguageServerEvent("MacCrash", crashObject, crashCountObject);
1009+
previousCrashCount = data === previousCrashData ? previousCrashCount + 1 : 0;
1010+
previousCrashData = data;
1011+
crashCountObject.CrashCount = previousCrashCount + 1;
1012+
telemetry.logLanguageServerEvent(type, crashObject, crashCountObject);
1013+
}
1014+
1015+
function logMacCrashTelemetry(data: string): void {
1016+
logCrashTelemetry(data, "MacCrash");
1017+
}
1018+
1019+
function logCppCrashTelemetry(data: string): void {
1020+
logCrashTelemetry(data, "CppCrash");
9731021
}
9741022

9751023
function handleMacCrashFileRead(err: NodeJS.ErrnoException | undefined | null, data: string): void {
@@ -1062,6 +1110,75 @@ function handleMacCrashFileRead(err: NodeJS.ErrnoException | undefined | null, d
10621110
logMacCrashTelemetry(data);
10631111
}
10641112

1113+
async function handleCrashFileRead(crashDirectory: string, crashFile: string, err: NodeJS.ErrnoException | undefined | null, data: string): Promise<void> {
1114+
if (err) {
1115+
if (err.code === "ENOENT") {
1116+
return; // ignore known issue
1117+
}
1118+
return logCppCrashTelemetry("readFile: " + err.code);
1119+
}
1120+
1121+
const lines: string[] = data.split("\n");
1122+
data = crashFile + "\n";
1123+
const filtPath: string | null = which.sync("c++filt", { nothrow: true });
1124+
const isMac: boolean = process.platform === "darwin";
1125+
const startStr: string = isMac ? " _" : "(_";
1126+
const offsetStr: string = isMac ? " + " : "+0x";
1127+
const dotStr: string = "…";
1128+
for (let lineNum: number = 2; lineNum < lines.length - 3; ++lineNum) { // skip first/last lines
1129+
if (lineNum > 2) {
1130+
data += "\n";
1131+
}
1132+
const line: string = lines[lineNum];
1133+
const startPos: number = line.indexOf(startStr);
1134+
if (startPos === -1) {
1135+
data += dotStr;
1136+
continue; // expected
1137+
}
1138+
const offsetPos: number = line.indexOf(offsetStr, startPos + startStr.length);
1139+
if (offsetPos === -1) {
1140+
data += `missing "${offsetStr}"`;
1141+
continue; // unexpected
1142+
}
1143+
const startPos2: number = startPos + 1;
1144+
let funcStr: string = line.substring(startPos2, offsetPos);
1145+
if (filtPath) {
1146+
const ret = await util.spawnChildProcess(filtPath, [funcStr], undefined, true).catch(logAndReturn.undefined);
1147+
if (ret !== undefined) {
1148+
funcStr = ret.output;
1149+
funcStr = funcStr.replace(/std::(?:__1|__cxx11)/g, "std"); // simplify std namespaces.
1150+
funcStr = funcStr.replace(/std::basic_/g, "std::");
1151+
funcStr = funcStr.replace(/ >/g, ">");
1152+
funcStr = funcStr.replace(/, std::(?:allocator|char_traits)<char>/g, "");
1153+
funcStr = funcStr.replace(/<char>/g, "");
1154+
funcStr = funcStr.replace(/, std::allocator<std::string>/g, "");
1155+
}
1156+
}
1157+
data += funcStr + offsetStr;
1158+
const offsetPos2: number = offsetPos + offsetStr.length;
1159+
if (isMac) {
1160+
data += line.substring(offsetPos2);
1161+
} else {
1162+
const endPos: number = line.indexOf(")", offsetPos2);
1163+
if (endPos === -1) {
1164+
data += "missing )";
1165+
continue; // unexpected
1166+
}
1167+
data += line.substring(offsetPos2, endPos);
1168+
}
1169+
}
1170+
1171+
if (data.length > 8192) { // The API has an 8k limit.
1172+
data = data.substring(0, 8191) + "…";
1173+
}
1174+
1175+
console.log(`Crash call stack:\n${data}`);
1176+
logCppCrashTelemetry(data);
1177+
1178+
await util.deleteFile(path.resolve(crashDirectory, crashFile)).catch(logAndReturn.undefined);
1179+
void util.deleteDirectory(crashDirectory).catch(logAndReturn.undefined);
1180+
}
1181+
10651182
export function deactivate(): Thenable<void> {
10661183
clients.timeTelemetryCollector.clear();
10671184
console.log("deactivating extension");

Extension/src/common.ts

+26-8
Original file line numberDiff line numberDiff line change
@@ -677,6 +677,22 @@ export function deleteFile(filePath: string): Promise<void> {
677677
});
678678
}
679679

680+
export function deleteDirectory(directoryPath: string): Promise<void> {
681+
return new Promise<void>((resolve, reject) => {
682+
if (fs.existsSync(directoryPath)) {
683+
fs.rmdir(directoryPath, (err) => {
684+
if (err) {
685+
reject(err);
686+
} else {
687+
resolve();
688+
}
689+
});
690+
} else {
691+
resolve();
692+
}
693+
});
694+
}
695+
680696
export function getReadmeMessage(): string {
681697
const readmePath: string = getExtensionFilePath("README.md");
682698
const readmeMessage: string = localize("refer.read.me", "Please refer to {0} for troubleshooting information. Issues can be created at {1}", readmePath, "https://github.com/Microsoft/vscode-cpptools/issues");
@@ -736,14 +752,16 @@ export interface ProcessReturnType {
736752
output: string;
737753
}
738754

739-
export async function spawnChildProcess(program: string, args: string[] = [], continueOn?: string, cancellationToken?: vscode.CancellationToken): Promise<ProcessReturnType> {
755+
export async function spawnChildProcess(program: string, args: string[] = [], continueOn?: string, skipLogging?: boolean, cancellationToken?: vscode.CancellationToken): Promise<ProcessReturnType> {
740756
// Do not use CppSettings to avoid circular require()
741-
const settings: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("C_Cpp", null);
742-
const loggingLevel: string | undefined = settings.get<string>("loggingLevel");
743-
if (loggingLevel === "Information" || loggingLevel === "Debug") {
744-
getOutputChannelLogger().appendLine(`$ ${program} ${args.join(' ')}`);
757+
if (skipLogging === undefined || !skipLogging) {
758+
const settings: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("C_Cpp", null);
759+
const loggingLevel: string | undefined = settings.get<string>("loggingLevel");
760+
if (loggingLevel === "Information" || loggingLevel === "Debug") {
761+
getOutputChannelLogger().appendLine(`$ ${program} ${args.join(' ')}`);
762+
}
745763
}
746-
const programOutput: ProcessOutput = await spawnChildProcessImpl(program, args, continueOn, cancellationToken);
764+
const programOutput: ProcessOutput = await spawnChildProcessImpl(program, args, continueOn, skipLogging, cancellationToken);
747765
const exitCode: number | NodeJS.Signals | undefined = programOutput.exitCode;
748766
if (programOutput.exitCode) {
749767
return { succeeded: false, exitCode, output: programOutput.stderr || programOutput.stdout || localize('process.exited', 'Process exited with code {0}', exitCode) };
@@ -765,12 +783,12 @@ interface ProcessOutput {
765783
stderr: string;
766784
}
767785

768-
async function spawnChildProcessImpl(program: string, args: string[], continueOn?: string, cancellationToken?: vscode.CancellationToken): Promise<ProcessOutput> {
786+
async function spawnChildProcessImpl(program: string, args: string[], continueOn?: string, skipLogging?: boolean, cancellationToken?: vscode.CancellationToken): Promise<ProcessOutput> {
769787
const result = new ManualPromise<ProcessOutput>();
770788

771789
// Do not use CppSettings to avoid circular require()
772790
const settings: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("C_Cpp", null);
773-
const loggingLevel: string | undefined = settings.get<string>("loggingLevel");
791+
const loggingLevel: string | undefined = (skipLogging === undefined || !skipLogging) ? settings.get<string>("loggingLevel") : "None";
774792

775793
let proc: child_process.ChildProcess;
776794
if (await isExecutable(program)) {

0 commit comments

Comments
 (0)