Compare commits
46
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fd482d2169 | ||
|
|
2fafd831e5 | ||
|
|
1ceae9d4ed | ||
|
|
d4d5d4551f | ||
|
|
0ef77b5616 | ||
|
|
efdc8e90f6 | ||
|
|
9f020e9258 | ||
|
|
c058568767 | ||
|
|
8809e69e91 | ||
|
|
7af5c40dd0 | ||
|
|
1d2bd10691 | ||
|
|
dac96fe852 | ||
|
|
a1487e5e79 | ||
|
|
6f19496172 | ||
|
|
76ccb791ff | ||
|
|
a5a5735089 | ||
|
|
5077edf585 | ||
|
|
f38926f8b1 | ||
|
|
30de9bcc27 | ||
|
|
100e2e0828 | ||
|
|
e3b41771c6 | ||
|
|
3f7f3090f6 | ||
|
|
4149493f2c | ||
|
|
43aad3f65c | ||
|
|
bedcacb0a1 | ||
|
|
a5f8f84b43 | ||
|
|
e53b190380 | ||
|
|
1846fd4001 | ||
|
|
62e09945e3 | ||
|
|
c9b0db02fd | ||
|
|
51da619eec | ||
|
|
3eb50568e9 | ||
|
|
866b145645 | ||
|
|
9762fe5397 | ||
|
|
377896c30a | ||
|
|
98f13a6f11 | ||
|
|
0d85aea687 | ||
|
|
25d2b76514 | ||
|
|
42dfef3f6b | ||
|
|
1ce1e9cd71 | ||
|
|
65163966d5 | ||
|
|
edf8e0a155 | ||
|
|
4083075476 | ||
|
|
b745ebc218 | ||
|
|
b69d17a0f5 | ||
|
|
be8b6fb693 |
+16
-1
@@ -1,7 +1,21 @@
|
||||
# C/C++ for Visual Studio Code Changelog
|
||||
|
||||
## Version 1.20.2: April 17, 2024
|
||||
## Version 1.20.4: March 2, 2024
|
||||
### Bug Fixes
|
||||
* Fix a couple crashes.
|
||||
|
||||
## Version 1.20.3: April 30, 2024
|
||||
### Enhancement
|
||||
* Log `cpptools` and `cpptool-srv` crash call stacks in the 'C/C++ Crash Call Stacks' Output channel for bug reporting (on x64 Linux and x64/arm64 Mac).
|
||||
|
||||
### Bug Fixes
|
||||
* Fix directories being incorrectly recursively traversed in certain cases. [#11993](https://github.com/microsoft/vscode-cpptools/issues/11993)
|
||||
* Fix a crash during startup. [#12237](https://github.com/microsoft/vscode-cpptools/issues/12237)
|
||||
* Fix IntelliSense configuration on Windows ARM64. [#12253](https://github.com/microsoft/vscode-cpptools/issues/12253)
|
||||
|
||||
## Version 1.20.2: April 22, 2024
|
||||
### Bug Fixes
|
||||
* Fix non-existent relative path variables not showing a warning in `c_cpp_properties.json` (and other related issues). [#12089](https://github.com/microsoft/vscode-cpptools/issues/12089)
|
||||
* Fix duplicate URIs in calls to provideConfigurations. [#12177](https://github.com/microsoft/vscode-cpptools/issues/12177)
|
||||
* Fix a crash and deadlock with a high `C_Cpp.loggingLevel`. [#12194](https://github.com/microsoft/vscode-cpptools/issues/12194)
|
||||
* Fix handling of `-iquote` for code analysis and `#include` completions. [#12198](https://github.com/microsoft/vscode-cpptools/issues/12198)
|
||||
@@ -24,6 +38,7 @@
|
||||
### Bug Fixes
|
||||
* Fix an IntelliSense parsing issue. [#6183](https://github.com/microsoft/vscode-cpptools/issues/6183)
|
||||
* Fix 'Copy Declaration / Definition' code not being formatted. [#10956](https://github.com/microsoft/vscode-cpptools/issues/10956)
|
||||
* Fix semantic colorization of certain macro arguments. [#11416](https://github.com/microsoft/vscode-cpptools/issues/11416)
|
||||
* Fix 'Create Declaration / Definition' not working if the cursor isn't on the function name. [#11834](https://github.com/microsoft/vscode-cpptools/issues/11834)
|
||||
* Fix duplicate 'Add #include' code actions. [#11989](https://github.com/microsoft/vscode-cpptools/issues/11989)
|
||||
* Fix `forcedInclude` resolution for relative paths. [PR #12035](https://github.com/microsoft/vscode-cpptools/pull/12035)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "cpptools",
|
||||
"displayName": "C/C++",
|
||||
"description": "C/C++ IntelliSense, debugging, and code browsing.",
|
||||
"version": "1.20.2-main",
|
||||
"version": "1.20.4-main",
|
||||
"publisher": "ms-vscode",
|
||||
"icon": "LanguageCCPP_color_128x.png",
|
||||
"readme": "README.md",
|
||||
|
||||
@@ -2001,8 +2001,8 @@ export class DefaultClient implements Client {
|
||||
}
|
||||
try {
|
||||
DefaultClient.isStarted.reset();
|
||||
const status = await this.provideCustomConfigurationAsync(docUri, requestFile, replaceExisting, provider);
|
||||
telemetry.logLanguageServerEvent('provideCustomConfiguration', { providerId, status });
|
||||
const resultCode = await this.provideCustomConfigurationAsync(docUri, requestFile, replaceExisting, provider);
|
||||
telemetry.logLanguageServerEvent('provideCustomConfiguration', { providerId, resultCode });
|
||||
} finally {
|
||||
onFinished();
|
||||
DefaultClient.isStarted.resolve();
|
||||
|
||||
@@ -1838,9 +1838,9 @@ export class CppProperties {
|
||||
curText = curText.substring(0, nextNameStart2);
|
||||
}
|
||||
if (this.prevSquiggleMetrics.get(currentConfiguration.name) === undefined) {
|
||||
this.prevSquiggleMetrics.set(currentConfiguration.name, { PathNonExistent: 0, PathNotAFile: 0, PathNotADirectory: 0, CompilerPathMissingQuotes: 0, CompilerModeMismatch: 0 });
|
||||
this.prevSquiggleMetrics.set(currentConfiguration.name, { PathNonExistent: 0, PathNotAFile: 0, PathNotADirectory: 0, CompilerPathMissingQuotes: 0, CompilerModeMismatch: 0, MultiplePathsNotAllowed: 0 });
|
||||
}
|
||||
const newSquiggleMetrics: { [key: string]: number } = { PathNonExistent: 0, PathNotAFile: 0, PathNotADirectory: 0, CompilerPathMissingQuotes: 0, CompilerModeMismatch: 0 };
|
||||
const newSquiggleMetrics: { [key: string]: number } = { PathNonExistent: 0, PathNotAFile: 0, PathNotADirectory: 0, CompilerPathMissingQuotes: 0, CompilerModeMismatch: 0, MultiplePathsNotAllowed: 0 };
|
||||
const isWindows: boolean = os.platform() === 'win32';
|
||||
|
||||
// TODO: Add other squiggles.
|
||||
@@ -1867,7 +1867,7 @@ export class CppProperties {
|
||||
}
|
||||
|
||||
// Check for path-related squiggles.
|
||||
let paths: string[] = [];
|
||||
const paths: string[] = [];
|
||||
let compilerPath: string | undefined;
|
||||
for (const pathArray of [ currentConfiguration.browse ? currentConfiguration.browse.path : undefined,
|
||||
currentConfiguration.includePath, currentConfiguration.macFrameworkPath ]) {
|
||||
@@ -1895,10 +1895,7 @@ export class CppProperties {
|
||||
compilerPath = currentConfiguration.compilerPath;
|
||||
}
|
||||
|
||||
// Resolve and split any environment variables
|
||||
paths = this.resolveAndSplit(paths, undefined, this.ExtendedEnvironment);
|
||||
compilerPath = util.resolveVariables(compilerPath, this.ExtendedEnvironment).trim();
|
||||
compilerPath = this.resolvePath(compilerPath);
|
||||
compilerPath = this.resolvePath(compilerPath).trim();
|
||||
|
||||
// Get the start/end for properties that are file-only.
|
||||
const forcedIncludeStart: number = curText.search(/\s*\"forcedInclude\"\s*:\s*\[/);
|
||||
@@ -1961,8 +1958,7 @@ export class CppProperties {
|
||||
let dotConfigMessage: string | undefined;
|
||||
|
||||
dotConfigPath = currentConfiguration.dotConfig;
|
||||
dotConfigPath = util.resolveVariables(dotConfigPath, this.ExtendedEnvironment).trim();
|
||||
dotConfigPath = this.resolvePath(dotConfigPath);
|
||||
dotConfigPath = this.resolvePath(dotConfigPath).trim();
|
||||
// does not try resolve if the dotConfig property is empty
|
||||
dotConfigPath = dotConfigPath !== '' ? dotConfigPath : undefined;
|
||||
|
||||
@@ -2001,25 +1997,6 @@ export class CppProperties {
|
||||
continue;
|
||||
}
|
||||
|
||||
let resolvedPath: string = this.resolvePath(curPath);
|
||||
if (!resolvedPath) {
|
||||
continue;
|
||||
}
|
||||
let pathExists: boolean = true;
|
||||
if (this.rootUri) {
|
||||
const checkPathExists: any = util.checkPathExistsSync(resolvedPath, this.rootUri.fsPath + path.sep, isWindows, false);
|
||||
pathExists = checkPathExists.pathExists;
|
||||
resolvedPath = checkPathExists.path;
|
||||
}
|
||||
// Normalize path separators.
|
||||
if (path.sep === "/") {
|
||||
resolvedPath = resolvedPath.replace(/\\/g, path.sep);
|
||||
} else {
|
||||
resolvedPath = resolvedPath.replace(/\//g, path.sep);
|
||||
}
|
||||
|
||||
// Iterate through the text and apply squiggles.
|
||||
|
||||
// Escape the path string for literal use in a regular expression
|
||||
// Need to escape any quotes to match the original text
|
||||
let escapedPath: string = curPath.replace(/"/g, '\\"');
|
||||
@@ -2030,6 +2007,42 @@ export class CppProperties {
|
||||
const pattern: RegExp = new RegExp(`"[^"]*?(?<="|;)${escapedPath}(?="|;).*?"`, "g");
|
||||
const configMatches: string[] | null = curText.match(pattern);
|
||||
|
||||
const expandedPaths: string[] = this.resolveAndSplit([curPath], undefined, this.ExtendedEnvironment, true, true);
|
||||
const incorrectExpandedPaths: string[] = [];
|
||||
|
||||
if (expandedPaths.length <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (this.rootUri) {
|
||||
for (const [index, expandedPath] of expandedPaths.entries()) {
|
||||
if (expandedPath.includes("${workspaceFolder}")) {
|
||||
expandedPaths[index] = this.resolvePath(expandedPath, false);
|
||||
} else {
|
||||
expandedPaths[index] = this.resolvePath(expandedPath);
|
||||
}
|
||||
|
||||
const checkPathExists: any = util.checkPathExistsSync(expandedPaths[index], this.rootUri.fsPath + path.sep, isWindows, false);
|
||||
if (!checkPathExists.pathExists) {
|
||||
// If there are multiple paths, store any non-existing paths to squiggle later on.
|
||||
incorrectExpandedPaths.push(expandedPaths[index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const pathExists: boolean = incorrectExpandedPaths.length === 0;
|
||||
|
||||
for (const [index, expandedPath] of expandedPaths.entries()) {
|
||||
// Normalize path separators.
|
||||
if (path.sep === "/") {
|
||||
expandedPaths[index] = expandedPath.replace(/\\/g, path.sep);
|
||||
} else {
|
||||
expandedPaths[index] = expandedPath.replace(/\//g, path.sep);
|
||||
}
|
||||
}
|
||||
|
||||
// Iterate through the text and apply squiggles.
|
||||
|
||||
let globPath: boolean = false;
|
||||
const asteriskPosition = curPath.indexOf("*");
|
||||
if (asteriskPosition !== -1) {
|
||||
@@ -2041,6 +2054,7 @@ export class CppProperties {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (configMatches && !globPath) {
|
||||
let curOffset: number = 0;
|
||||
let endOffset: number = 0;
|
||||
@@ -2050,29 +2064,57 @@ export class CppProperties {
|
||||
if (curOffset >= compilerPathStart && curOffset <= compilerPathEnd) {
|
||||
continue;
|
||||
}
|
||||
let message: string;
|
||||
let message: string = "";
|
||||
if (!pathExists) {
|
||||
if (curOffset >= forcedIncludeStart && curOffset <= forcedeIncludeEnd
|
||||
&& !path.isAbsolute(resolvedPath)) {
|
||||
&& !path.isAbsolute(expandedPaths[0])) {
|
||||
continue; // Skip the error, because it could be resolved recursively.
|
||||
}
|
||||
message = localize('cannot.find2', "Cannot find \"{0}\".", resolvedPath);
|
||||
let badPath = "";
|
||||
if (incorrectExpandedPaths.length > 0) {
|
||||
badPath = incorrectExpandedPaths.map(s => `"${s}"`).join(', ');
|
||||
} else {
|
||||
badPath = `"${expandedPaths[0]}"`;
|
||||
}
|
||||
message = localize('cannot.find2', "Cannot find {0}", badPath);
|
||||
newSquiggleMetrics.PathNonExistent++;
|
||||
} else {
|
||||
// Check for file versus path mismatches.
|
||||
if ((curOffset >= forcedIncludeStart && curOffset <= forcedeIncludeEnd) ||
|
||||
(curOffset >= compileCommandsStart && curOffset <= compileCommandsEnd)) {
|
||||
if (util.checkFileExistsSync(resolvedPath)) {
|
||||
continue;
|
||||
(curOffset >= compileCommandsStart && curOffset <= compileCommandsEnd)) {
|
||||
if (expandedPaths.length > 1) {
|
||||
message = localize("multiple.paths.not.allowed", "Multiple paths are not allowed.");
|
||||
newSquiggleMetrics.MultiplePathsNotAllowed++;
|
||||
} else {
|
||||
const resolvedPath = this.resolvePath(expandedPaths[0]);
|
||||
if (util.checkFileExistsSync(resolvedPath)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
message = localize("path.is.not.a.file", "Path is not a file: {0}", expandedPaths[0]);
|
||||
newSquiggleMetrics.PathNotAFile++;
|
||||
}
|
||||
message = localize("path.is.not.a.file", "Path is not a file: {0}", resolvedPath);
|
||||
newSquiggleMetrics.PathNotAFile++;
|
||||
} else {
|
||||
if (util.checkDirectoryExistsSync(resolvedPath)) {
|
||||
const mismatchedPaths: string[] = [];
|
||||
for (const expandedPath of expandedPaths) {
|
||||
const resolvedPath = this.resolvePath(expandedPath);
|
||||
if (!util.checkDirectoryExistsSync(resolvedPath)) {
|
||||
mismatchedPaths.push(expandedPath);
|
||||
}
|
||||
}
|
||||
|
||||
let badPath = "";
|
||||
if (mismatchedPaths.length > 1) {
|
||||
badPath = mismatchedPaths.map(s => `"${s}"`).join(', ');
|
||||
message = localize('paths.are.not.directories', "Paths are not directories: {0}", badPath);
|
||||
newSquiggleMetrics.PathNotADirectory++;
|
||||
} else if (mismatchedPaths.length === 1) {
|
||||
badPath = `"${mismatchedPaths[0]}"`;
|
||||
message = localize('path.is.not.a.directory', "Path is not a directory: {0}", badPath);
|
||||
newSquiggleMetrics.PathNotADirectory++;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
message = localize("path.is.not.a.directory", "Path is not a directory: {0}", resolvedPath);
|
||||
newSquiggleMetrics.PathNotADirectory++;
|
||||
}
|
||||
}
|
||||
const diagnostic: vscode.Diagnostic = new vscode.Diagnostic(
|
||||
@@ -2092,7 +2134,7 @@ export class CppProperties {
|
||||
endOffset = curOffset + curMatch.length;
|
||||
let message: string;
|
||||
if (!pathExists) {
|
||||
message = localize('cannot.find2', "Cannot find \"{0}\".", resolvedPath);
|
||||
message = localize('cannot.find2', "Cannot find \"{0}\".", expandedPaths[0]);
|
||||
newSquiggleMetrics.PathNonExistent++;
|
||||
const diagnostic: vscode.Diagnostic = new vscode.Diagnostic(
|
||||
new vscode.Range(document.positionAt(envTextStartOffSet + curOffset),
|
||||
@@ -2128,6 +2170,9 @@ export class CppProperties {
|
||||
if (newSquiggleMetrics.CompilerModeMismatch !== this.prevSquiggleMetrics.get(currentConfiguration.name)?.CompilerModeMismatch) {
|
||||
changedSquiggleMetrics.CompilerModeMismatch = newSquiggleMetrics.CompilerModeMismatch;
|
||||
}
|
||||
if (newSquiggleMetrics.MultiplePathsNotAllowed !== this.prevSquiggleMetrics.get(currentConfiguration.name)?.MultiplePathsNotAllowed) {
|
||||
changedSquiggleMetrics.MultiplePathsNotAllowed = newSquiggleMetrics.MultiplePathsNotAllowed;
|
||||
}
|
||||
if (Object.keys(changedSquiggleMetrics).length > 0) {
|
||||
telemetry.logLanguageServerEvent("ConfigSquiggles", undefined, changedSquiggleMetrics);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import { TargetPopulation } from 'vscode-tas-client';
|
||||
import * as which from 'which';
|
||||
import { logAndReturn } from '../Utility/Async/returns';
|
||||
import * as util from '../common';
|
||||
import { getCrashCallStacksChannel } from '../logger';
|
||||
import { PlatformInformation } from '../platform';
|
||||
import * as telemetry from '../telemetry';
|
||||
import { Client, DefaultClient, DoxygenCodeActionCommandArguments, openFileVersions } from './client';
|
||||
@@ -36,7 +37,9 @@ const localize: nls.LocalizeFunc = nls.loadMessageBundle();
|
||||
export const CppSourceStr: string = "C/C++";
|
||||
export const configPrefix: string = "C/C++: ";
|
||||
|
||||
let prevCrashFile: string;
|
||||
let prevMacCrashFile: string;
|
||||
let prevCppCrashFile: string;
|
||||
let prevCppCrashCallStackData: string = "";
|
||||
export let clients: ClientCollection;
|
||||
let activeDocument: vscode.TextDocument | undefined;
|
||||
let ui: LanguageStatusUI;
|
||||
@@ -914,7 +917,7 @@ function onShowRefCommand(arg?: TreeNode): void {
|
||||
|
||||
function reportMacCrashes(): void {
|
||||
if (process.platform === "darwin") {
|
||||
prevCrashFile = "";
|
||||
prevMacCrashFile = "";
|
||||
const home: string = os.homedir();
|
||||
const crashFolder: string = path.resolve(home, "Library/Logs/DiagnosticReports");
|
||||
fs.stat(crashFolder, (err) => {
|
||||
@@ -932,10 +935,10 @@ function reportMacCrashes(): void {
|
||||
if (event !== "rename") {
|
||||
return;
|
||||
}
|
||||
if (!filename || filename === prevCrashFile) {
|
||||
if (!filename || filename === prevMacCrashFile) {
|
||||
return;
|
||||
}
|
||||
prevCrashFile = filename;
|
||||
prevMacCrashFile = filename;
|
||||
if (!filename.startsWith("cpptools")) {
|
||||
return;
|
||||
}
|
||||
@@ -959,12 +962,24 @@ function reportMacCrashes(): void {
|
||||
}
|
||||
|
||||
export function usesCrashHandler(): boolean {
|
||||
return process.platform !== "win32" && (process.platform === "darwin" || os.arch() === "x64");
|
||||
if (os.platform() === "darwin") {
|
||||
if (os.arch() === "arm64") {
|
||||
return true;
|
||||
} else {
|
||||
const releaseParts: string[] = os.release().split(".");
|
||||
if (releaseParts.length >= 1) {
|
||||
// Avoid potentially intereferring with the older macOS crash handler.
|
||||
return parseInt(releaseParts[0]) < 19;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return os.platform() !== "win32" && os.arch() === "x64";
|
||||
}
|
||||
|
||||
export function watchForCrashes(crashDirectory: string): void {
|
||||
if (crashDirectory !== "") {
|
||||
prevCrashFile = "";
|
||||
prevCppCrashFile = "";
|
||||
fs.stat(crashDirectory, (err) => {
|
||||
const crashObject: Record<string, string> = {};
|
||||
if (err?.code) {
|
||||
@@ -980,17 +995,19 @@ export function watchForCrashes(crashDirectory: string): void {
|
||||
if (event !== "rename") {
|
||||
return;
|
||||
}
|
||||
if (!filename || filename === prevCrashFile) {
|
||||
if (!filename || filename === prevCppCrashFile) {
|
||||
return;
|
||||
}
|
||||
prevCrashFile = filename;
|
||||
prevCppCrashFile = filename;
|
||||
if (!filename.startsWith("cpptools")) {
|
||||
return;
|
||||
}
|
||||
const crashDate: Date = new Date();
|
||||
|
||||
// Wait 5 seconds to allow time for the crash log to finish being written.
|
||||
setTimeout(() => {
|
||||
fs.readFile(path.resolve(crashDirectory, filename), 'utf8', (err, data) => {
|
||||
void handleCrashFileRead(crashDirectory, filename, err, data);
|
||||
void handleCrashFileRead(crashDirectory, filename, crashDate, err, data);
|
||||
});
|
||||
}, 5000);
|
||||
});
|
||||
@@ -1115,7 +1132,7 @@ function handleMacCrashFileRead(err: NodeJS.ErrnoException | undefined | null, d
|
||||
logMacCrashTelemetry(data);
|
||||
}
|
||||
|
||||
async function handleCrashFileRead(crashDirectory: string, crashFile: string, err: NodeJS.ErrnoException | undefined | null, data: string): Promise<void> {
|
||||
async function handleCrashFileRead(crashDirectory: string, crashFile: string, crashDate: Date, err: NodeJS.ErrnoException | undefined | null, data: string): Promise<void> {
|
||||
if (err) {
|
||||
if (err.code === "ENOENT") {
|
||||
return; // ignore known issue
|
||||
@@ -1125,23 +1142,23 @@ async function handleCrashFileRead(crashDirectory: string, crashFile: string, er
|
||||
|
||||
const lines: string[] = data.split("\n");
|
||||
let addressData: string = ".\n.";
|
||||
data = crashFile + "\n";
|
||||
const isCppToolsSrv: boolean = crashFile.startsWith("cpptools-srv");
|
||||
const telemetryHeader: string = (isCppToolsSrv ? "cpptools-srv.txt" : crashFile) + "\n";
|
||||
const filtPath: string | null = which.sync("c++filt", { nothrow: true });
|
||||
const isMac: boolean = process.platform === "darwin";
|
||||
const startStr: string = isMac ? " _" : "<";
|
||||
const offsetStr: string = isMac ? " + " : "+";
|
||||
const endOffsetStr: string = isMac ? " " : " <";
|
||||
const dotStr: string = "…";
|
||||
data += lines[0]; // signal type
|
||||
const signalType: string = lines[0];
|
||||
let crashCallStack: string = "";
|
||||
for (let lineNum: number = 2; lineNum < lines.length - 3; ++lineNum) { // skip first/last lines
|
||||
if (lineNum > 1) {
|
||||
data += "\n";
|
||||
addressData += "\n";
|
||||
}
|
||||
crashCallStack += "\n";
|
||||
addressData += "\n";
|
||||
const line: string = lines[lineNum];
|
||||
const startPos: number = line.indexOf(startStr);
|
||||
if (startPos === -1 || line[startPos + (isMac ? 1 : 4)] === "+") {
|
||||
data += dotStr;
|
||||
crashCallStack += dotStr;
|
||||
const startAddressPos: number = line.indexOf("0x");
|
||||
const endAddressPos: number = line.indexOf(endOffsetStr, startAddressPos + 2);
|
||||
if (startAddressPos === -1 || endAddressPos === -1 || startAddressPos >= endAddressPos) {
|
||||
@@ -1153,7 +1170,7 @@ async function handleCrashFileRead(crashDirectory: string, crashFile: string, er
|
||||
}
|
||||
const offsetPos: number = line.indexOf(offsetStr, startPos + startStr.length);
|
||||
if (offsetPos === -1) {
|
||||
data += "Missing offsetStr";
|
||||
crashCallStack += "Missing offsetStr";
|
||||
continue; // unexpected
|
||||
}
|
||||
const startPos2: number = startPos + 1;
|
||||
@@ -1173,36 +1190,49 @@ async function handleCrashFileRead(crashDirectory: string, crashFile: string, er
|
||||
funcStr = funcStr.replace(/, std::allocator<std::string>/g, "");
|
||||
}
|
||||
}
|
||||
data += funcStr + offsetStr;
|
||||
crashCallStack += funcStr + offsetStr;
|
||||
const offsetPos2: number = offsetPos + offsetStr.length;
|
||||
if (isMac) {
|
||||
data += line.substring(offsetPos2);
|
||||
crashCallStack += line.substring(offsetPos2);
|
||||
const startAddressPos: number = line.indexOf("0x");
|
||||
if (startAddressPos === -1 || startAddressPos >= startPos) {
|
||||
// unexpected
|
||||
data += "<Missing 0x>";
|
||||
crashCallStack += "<Missing 0x>";
|
||||
continue;
|
||||
}
|
||||
addressData += `${line.substring(startAddressPos, startPos)}`;
|
||||
} else {
|
||||
const endPos: number = line.indexOf(">", offsetPos2);
|
||||
if (endPos === -1) {
|
||||
data += "<Missing > >";
|
||||
crashCallStack += "<Missing > >";
|
||||
continue; // unexpected
|
||||
}
|
||||
data += line.substring(offsetPos2, endPos);
|
||||
crashCallStack += line.substring(offsetPos2, endPos);
|
||||
}
|
||||
}
|
||||
|
||||
if (crashCallStack !== prevCppCrashCallStackData) {
|
||||
prevCppCrashCallStackData = crashCallStack;
|
||||
|
||||
const settings: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("C_Cpp", null);
|
||||
if (lines.length >= 6 && util.getNumericLoggingLevel(settings.get<string>("loggingLevel")) >= 1) {
|
||||
const out: vscode.OutputChannel = getCrashCallStacksChannel();
|
||||
out.appendLine(`\n${isCppToolsSrv ? "cpptools-srv" : "cpptools"}\n${crashDate.toLocaleString()}\n${signalType}${crashCallStack}`);
|
||||
}
|
||||
}
|
||||
|
||||
data = telemetryHeader + signalType + crashCallStack;
|
||||
|
||||
if (data.length > 8192) { // The API has an 8k limit.
|
||||
data = data.substring(0, 8191) + "…";
|
||||
}
|
||||
|
||||
console.log(`Crash call stack:\n${data}`);
|
||||
logCppCrashTelemetry(data, addressData);
|
||||
|
||||
await util.deleteFile(path.resolve(crashDirectory, crashFile)).catch(logAndReturn.undefined);
|
||||
void util.deleteDirectory(crashDirectory).catch(logAndReturn.undefined);
|
||||
if (crashFile === "cpptools.txt") {
|
||||
void util.deleteDirectory(crashDirectory).catch(logAndReturn.undefined);
|
||||
}
|
||||
}
|
||||
|
||||
export function deactivate(): Thenable<void> {
|
||||
|
||||
@@ -74,6 +74,7 @@ export class Logger {
|
||||
|
||||
export let outputChannel: vscode.OutputChannel | undefined;
|
||||
export let diagnosticsChannel: vscode.OutputChannel | undefined;
|
||||
export let crashCallStacksChannel: vscode.OutputChannel | undefined;
|
||||
export let debugChannel: vscode.OutputChannel | undefined;
|
||||
export let warningChannel: vscode.OutputChannel | undefined;
|
||||
export let sshChannel: vscode.OutputChannel | undefined;
|
||||
@@ -98,6 +99,16 @@ export function getDiagnosticsChannel(): vscode.OutputChannel {
|
||||
return diagnosticsChannel;
|
||||
}
|
||||
|
||||
export function getCrashCallStacksChannel(): vscode.OutputChannel {
|
||||
if (!crashCallStacksChannel) {
|
||||
crashCallStacksChannel = vscode.window.createOutputChannel(localize("c.cpp.crash.call.stacks.title", "C/C++ Crash Call Stacks"));
|
||||
crashCallStacksChannel.appendLine(localize({ key: "c.cpp.crash.call.stacks.description", comment: ["{0} is a URL."] },
|
||||
"A C/C++ extension process has crashed. The crashing process name, date/time, signal, and call stack are below -- it would be helpful to include that in a bug report at {0}.",
|
||||
"https://github.com/Microsoft/vscode-cpptools/issues"));
|
||||
}
|
||||
return crashCallStacksChannel;
|
||||
}
|
||||
|
||||
export function getSshChannel(): vscode.OutputChannel {
|
||||
if (!sshChannel) {
|
||||
sshChannel = vscode.window.createOutputChannel(localize("c.cpp.ssh.channel", "{0}: SSH", "Cpptools"));
|
||||
|
||||
Reference in New Issue
Block a user