diff --git a/Extension/CHANGELOG.md b/Extension/CHANGELOG.md index 606fb27f5..da554b2e1 100644 --- a/Extension/CHANGELOG.md +++ b/Extension/CHANGELOG.md @@ -1,8 +1,24 @@ # C/C++ for Visual Studio Code Changelog -## Version 1.23.0: October 24, 2024 +### Version 1.23.1: November 6, 2024 +### Bug Fixes +* A potential fix for a crash during process shutdown (in `uv_run`). [#12668](https://github.com/microsoft/vscode-cpptools/issues/12668) +* Fix a performance issue where some LSP requests would delay other LSP requests. [#12905](https://github.com/microsoft/vscode-cpptools/issues/12905) +* A potential fix for a crash in cpptools (in `report_intellisense_results`). +* Fix a random deadlock with `compiler_info::find_or_create`. +* Fix a random deadlock with `handle_edits`. +* Other internal fixes. + +## Version 1.22.11: November 5, 2024 +### Bug Fixes +* Fix system includes incorrectly being treated as non-system includes when specified with `-I`. [#12842](https://github.com/microsoft/vscode-cpptools/issues/12842) +* Fix inactive region ranges when multi-byte UTF-8 characters are used. [#12879](https://github.com/microsoft/vscode-cpptools/issues/12879) +* Fix formatting with `.editorconfig` files. [#12921](https://github.com/microsoft/vscode-cpptools/issues/12921) + +## Version 1.23.0: October 29, 2024 ### Enhancements * Update to clang-format and clang-tidy 19.1.2. [#12824](https://github.com/microsoft/vscode-cpptools/issues/12824) +* Enable `#cpp` with GitHub Copilot chat without `C_Cpp.experimentalFeatures` enabled. [PR #12898](https://github.com/microsoft/vscode-cpptools/pull/12898) ### Bug Fixes * Fix some translation issues. [#7824](https://github.com/microsoft/vscode-cpptools/issues/7824), [#12439](https://github.com/microsoft/vscode-cpptools/issues/12439), [#12440](https://github.com/microsoft/vscode-cpptools/issues/12440), [#12441](https://github.com/microsoft/vscode-cpptools/issues/12441) diff --git a/Extension/ThirdPartyNotices.txt b/Extension/ThirdPartyNotices.txt index e7ba616c5..3dc5f2feb 100644 --- a/Extension/ThirdPartyNotices.txt +++ b/Extension/ThirdPartyNotices.txt @@ -2429,6 +2429,7 @@ The notices below are from non-npm sources. - ANTLR (http://www.antlr2.org/) - C++11 Sublime Text Snippets (https://github.com/Rapptz/cpp-sublime-snippet) - Clang (https://clang.llvm.org/) +- editorconfig-core-js (https://github.com/editorconfig/editorconfig-core-js) - gcc-11/libgcc (https://packages.ubuntu.com/jammy/gcc-11-base) - Guidelines Support Library (https://github.com/Microsoft/GSL) - libc++ (https://libcxx.llvm.org/index.html) @@ -2677,6 +2678,31 @@ mechanisms: ========================================= END OF Clang NOTICES AND INFORMATION +%% editorconfig-core-js NOTICES AND INFORMATION BEGIN HERE +========================================= +Copyright © 2012 EditorConfig Team + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the “Software”), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +========================================= +END OF editorconfig-core-js NOTICES AND INFORMATION + %% gcc-9/libgcc NOTICES AND INFORMATION BEGIN HERE ========================================= The following runtime libraries are licensed under the terms of the diff --git a/Extension/package.json b/Extension/package.json index df3a34df2..c62ff41dd 100644 --- a/Extension/package.json +++ b/Extension/package.json @@ -2,7 +2,7 @@ "name": "cpptools", "displayName": "C/C++", "description": "C/C++ IntelliSense, debugging, and code browsing.", - "version": "1.23.0-main", + "version": "1.23.1-main", "publisher": "ms-vscode", "icon": "LanguageCCPP_color_128x.png", "readme": "README.md", @@ -6522,13 +6522,12 @@ "translations-generate": "set NODE_OPTIONS=--no-experimental-fetch && gulp translations-generate", "translations-import": "gulp translations-import", "import-edge-strings": "ts-node -T ./.scripts/import_edge_strings.ts", - "prep:dts": "yarn verify dts --quiet || (npx vscode-dts dev && npx vscode-dts main)", + "prep:dts": "yarn verify dts --quiet || (npx @vscode/dts dev && npx @vscode/dts main)", "build": "yarn prep:dts && echo [Building TypeScript code] && tsc --build tsconfig.json" }, "devDependencies": { "@octokit/rest": "^20.1.1", "@types/glob": "^7.2.0", - "@types/minimatch": "^3.0.5", "@types/mocha": "^10.0.6", "@types/node": "^20.14.2", "@types/node-fetch": "^2.6.11", @@ -6580,7 +6579,7 @@ "comment-json": "^4.2.3", "escape-string-regexp": "^2.0.0", "glob": "^7.2.3", - "minimatch": "^3.0.5", + "minimatch": "^4.2.0", "mkdirp": "^3.0.1", "node-fetch": "^2.7.0", "node-loader": "^2.0.0", diff --git a/Extension/src/Debugger/configurationProvider.ts b/Extension/src/Debugger/configurationProvider.ts index 2b9ce38ac..067983fea 100644 --- a/Extension/src/Debugger/configurationProvider.ts +++ b/Extension/src/Debugger/configurationProvider.ts @@ -331,7 +331,7 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv // Run deploy steps if (config.deploySteps && config.deploySteps.length !== 0) { - const codeVersion: number[] = vscode.version.split('.').map(num => parseInt(num, undefined)); + const codeVersion: number[] = util.getVsCodeVersion(); if ((util.isNumber(codeVersion[0]) && codeVersion[0] < 1) || (util.isNumber(codeVersion[0]) && codeVersion[0] === 1 && util.isNumber(codeVersion[1]) && codeVersion[1] < 69)) { void logger.getOutputChannelLogger().showErrorMessage(localize("vs.code.1.69+.required", "'deploySteps' require VS Code 1.69+.")); return undefined; diff --git a/Extension/src/LanguageServer/client.ts b/Extension/src/LanguageServer/client.ts index ef2c34250..1635a314f 100644 --- a/Extension/src/LanguageServer/client.ts +++ b/Extension/src/LanguageServer/client.ts @@ -1307,6 +1307,12 @@ export class DefaultClient implements Client { // Listen for messages from the language server. this.registerNotifications(); + + // If a file is already open when we activate, sometimes we don't get any notifications about visible + // or active text editors, visible ranges, or text selection. As a workaround, we trigger + // onDidChangeVisibleTextEditors here. + const cppEditors: vscode.TextEditor[] = vscode.window.visibleTextEditors.filter(e => util.isCpp(e.document)); + await this.onDidChangeVisibleTextEditors(cppEditors); } // update all client configurations @@ -2603,7 +2609,8 @@ export class DefaultClient implements Client { } let foundGlobMatch: boolean = false; for (const assoc in assocs) { - if (minimatch(filePath, assoc)) { + const matcher = new minimatch.Minimatch(assoc); + if (matcher.match(filePath)) { foundGlobMatch = true; break; // Assoc matched a glob pattern. } diff --git a/Extension/src/LanguageServer/configurations.ts b/Extension/src/LanguageServer/configurations.ts index 3a02622b0..6f23eb347 100644 --- a/Extension/src/LanguageServer/configurations.ts +++ b/Extension/src/LanguageServer/configurations.ts @@ -138,7 +138,7 @@ export class CppProperties { private configFileWatcherFallbackTime: Date = new Date(); // Used when file watching fails. private compileCommandsFile: vscode.Uri | undefined | null = undefined; private compileCommandsFileWatchers: fs.FSWatcher[] = []; - private compileCommandsFileWatcherFallbackTime: Date = new Date(); // Used when file watching fails. + private compileCommandsFileWatcherFallbackTime: Map = new Map(); // Used when file watching fails. private defaultCompilerPath: string | null = null; private knownCompilers?: KnownCompiler[]; private defaultCStandard: string | null = null; @@ -1093,6 +1093,10 @@ export class CppProperties { if (configuration.compileCommands) { configuration.compileCommands = this.resolvePath(configuration.compileCommands); + if (!this.compileCommandsFileWatcherFallbackTime.has(configuration.compileCommands)) { + // Start tracking the fallback time for a new path. + this.compileCommandsFileWatcherFallbackTime.set(configuration.compileCommands, new Date()); + } } if (configuration.forcedInclude) { @@ -1104,12 +1108,31 @@ export class CppProperties { } } + this.clearStaleCompileCommandsFileWatcherFallbackTimes(); this.updateCompileCommandsFileWatchers(); if (!this.configurationIncomplete) { this.onConfigurationsChanged(); } } + private clearStaleCompileCommandsFileWatcherFallbackTimes(): void { + // We need to keep track of relevant timestamps, so we cannot simply clear all entries. + // Instead, we clear entries that are no longer relevant. + const trackedCompileCommandsPaths: Set = new Set(); + this.configurationJson?.configurations.forEach((config: Configuration) => { + const path = this.resolvePath(config.compileCommands); + if (path.length > 0) { + trackedCompileCommandsPaths.add(path); + } + }); + + for (const path of this.compileCommandsFileWatcherFallbackTime.keys()) { + if (!trackedCompileCommandsPaths.has(path)) { + this.compileCommandsFileWatcherFallbackTime.delete(path); + } + } + } + private compileCommandsFileWatcherTimer?: NodeJS.Timeout; private compileCommandsFileWatcherFiles: Set = new Set(); @@ -1948,7 +1971,7 @@ export class CppProperties { compilerPath = checkPathExists.path; } if (!compilerPathExists) { - compilerMessage = localize('cannot.find2', "Cannot find \"{0}\".", compilerPath); + compilerMessage = localize('cannot.find', "Cannot find: {0}", compilerPath); newSquiggleMetrics.PathNonExistent++; } if (compilerMessage) { @@ -1975,7 +1998,7 @@ export class CppProperties { dotConfigPath = checkPathExists.path; } if (!dotConfigPathExists) { - dotConfigMessage = localize('cannot.find2', "Cannot find \"{0}\".", dotConfigPath); + dotConfigMessage = localize('cannot.find', "Cannot find: {0}", dotConfigPath); newSquiggleMetrics.PathNonExistent++; } else if (dotConfigPath && !util.checkFileExistsSync(dotConfigPath)) { dotConfigMessage = localize("path.is.not.a.file", "Path is not a file: {0}", dotConfigPath); @@ -2083,7 +2106,7 @@ export class CppProperties { } else { badPath = `"${expandedPaths[0]}"`; } - message = localize('cannot.find2', "Cannot find {0}", badPath); + message = localize('cannot.find', "Cannot find: {0}", badPath); newSquiggleMetrics.PathNonExistent++; } else { // Check for file versus path mismatches. @@ -2141,7 +2164,7 @@ export class CppProperties { endOffset = curOffset + curMatch.length; let message: string; if (!pathExists) { - message = localize('cannot.find2', "Cannot find \"{0}\".", expandedPaths[0]); + message = localize('cannot.find', "Cannot find: {0}", expandedPaths[0]); newSquiggleMetrics.PathNonExistent++; const diagnostic: vscode.Diagnostic = new vscode.Diagnostic( new vscode.Range(document.positionAt(envTextStartOffSet + curOffset), @@ -2310,14 +2333,18 @@ export class CppProperties { fs.stat(compileCommandsFile, (err, stats) => { if (err) { if (err.code === "ENOENT" && this.compileCommandsFile) { + this.compileCommandsFileWatchers.forEach((watcher: fs.FSWatcher) => watcher.close()); this.compileCommandsFileWatchers = []; // reset file watchers this.onCompileCommandsChanged(compileCommandsFile); this.compileCommandsFile = null; // File deleted } - } else if (stats.mtime > this.compileCommandsFileWatcherFallbackTime) { - this.compileCommandsFileWatcherFallbackTime = new Date(); - this.onCompileCommandsChanged(compileCommandsFile); - this.compileCommandsFile = vscode.Uri.file(compileCommandsFile); // File created. + } else { + const compileCommandsLastChanged: Date | undefined = this.compileCommandsFileWatcherFallbackTime.get(compileCommandsFile); + if (compileCommandsLastChanged !== undefined && stats.mtime > compileCommandsLastChanged) { + this.compileCommandsFileWatcherFallbackTime.set(compileCommandsFile, new Date()); + this.onCompileCommandsChanged(compileCommandsFile); + this.compileCommandsFile = vscode.Uri.file(compileCommandsFile); // File created. + } } }); } diff --git a/Extension/src/LanguageServer/editorConfig.ts b/Extension/src/LanguageServer/editorConfig.ts index 1ac8452b4..b5c8aa1db 100644 --- a/Extension/src/LanguageServer/editorConfig.ts +++ b/Extension/src/LanguageServer/editorConfig.ts @@ -5,7 +5,9 @@ 'use strict'; import * as fs from 'fs'; +import { Minimatch } from 'minimatch'; import * as path from 'path'; +import { isWindows } from '../constants'; export const cachedEditorConfigSettings: Map = new Map(); @@ -61,13 +63,25 @@ export function mapWrapToEditorConfig(value: string | undefined): string { return "never"; } -function matchesSection(filePath: string, section: string): boolean { - const fileName: string = path.basename(filePath); - // Escape all regex special characters except '*' and '?'. - // Convert wildcards '*' to '.*' and '?' to '.'. - const sectionPattern = section.replace(/[.+^${}()|[\]\\]/g, '\\$&').replace(/\*/g, '.*').replace(/\?/g, '.'); - const regex: RegExp = new RegExp(`^${sectionPattern}$`); - return regex.test(fileName); +export function matchesSection(pathPrefix: string, filePath: string, section: string): boolean { + // The following code is copied from: https://github.com/editorconfig/editorconfig-core-js + const matchOptions = { matchBase: true, dot: true }; + pathPrefix = pathPrefix.replace(/[?*+@!()|[\]{}]/g, '\\$&'); + pathPrefix = pathPrefix.replace(/^#/, '\\#'); + switch (section.indexOf('/')) { + case -1: + section = `**/${section}`; + break; + case 0: + section = section.substring(1); + break; + default: + break; + } + section = section.replace(/\\\\/g, '\\\\\\\\'); + section = section.replace(/\*\*/g, '{*,**/**/**}'); + const matcher = new Minimatch(`${pathPrefix}/${section}`, matchOptions); + return matcher.match(filePath); } function parseEditorConfigContent(content: string): Record { @@ -92,7 +106,17 @@ function parseEditorConfigContent(content: string): Record { const [key, ...values] = line.split('='); if (key && values.length > 0) { const trimmedKey = key.trim(); - const value = values.join('=').trim(); + let value: any = values.join('=').trim(); + + // Convert boolean-like and numeric values. + if (value === 'true') { + value = true; + } else if (value === 'false') { + value = false; + } else if (!isNaN(Number(value))) { + value = Number(value); + } + if (currentSection) { // Ensure the current section is initialized. if (!config[currentSection]) { @@ -113,8 +137,12 @@ function getEditorConfig(filePath: string): any { let currentDir: string = path.dirname(filePath); const rootDir: string = path.parse(currentDir).root; + if (isWindows) { + filePath = filePath.replace(/\\/g, '/'); + } + // Traverse from the file's directory to the root directory. - for (;;) { + for (; ;) { const editorConfigPath: string = path.join(currentDir, '.editorconfig'); if (fs.existsSync(editorConfigPath)) { const configFileContent: string = fs.readFileSync(editorConfigPath, 'utf-8'); @@ -128,9 +156,14 @@ function getEditorConfig(filePath: string): any { }; } + let currentDirForwardSlashes: string = currentDir; + if (isWindows) { + currentDirForwardSlashes = currentDir.replace(/\\/g, '/'); + } + // Match sections and combine configurations. Object.keys(configData).forEach((section: string) => { - if (section !== '*' && matchesSection(filePath, section)) { + if (section !== '*' && matchesSection(currentDirForwardSlashes, filePath, section)) { combinedConfig = { ...combinedConfig, ...configData[section] @@ -139,7 +172,7 @@ function getEditorConfig(filePath: string): any { }); // Check if the current .editorconfig is the root. - if (configData['*']?.root?.toLowerCase() === 'true') { + if (configData['*']?.root) { break; // Stop searching after processing the root = true file. } } diff --git a/Extension/src/LanguageServer/extension.ts b/Extension/src/LanguageServer/extension.ts index 78cc87c36..b7441625d 100644 --- a/Extension/src/LanguageServer/extension.ts +++ b/Extension/src/LanguageServer/extension.ts @@ -255,9 +255,15 @@ export async function activate(): Promise { activeDocument = activeEditor.document; } - if (util.extensionContext && new CppSettings().experimentalFeatures) { - const tool = vscode.lm.registerTool('cpptools-lmtool-configuration', new CppConfigurationLanguageModelTool()); - disposables.push(tool); + if (util.extensionContext) { + // lmTools wasn't stabilized until 1.95, but (as of October 2024) + // cpptools can be installed on older versions of VS Code. See + // https://github.com/microsoft/vscode-cpptools/blob/main/Extension/package.json#L14 + const version = util.getVsCodeVersion(); + if (version[0] > 1 || (version[0] === 1 && version[1] >= 95)) { + const tool = vscode.lm.registerTool('cpptools-lmtool-configuration', new CppConfigurationLanguageModelTool()); + disposables.push(tool); + } } await registerRelatedFilesProvider(); diff --git a/Extension/src/LanguageServer/lmTool.ts b/Extension/src/LanguageServer/lmTool.ts index ed5be61a0..c3fad8b6e 100644 --- a/Extension/src/LanguageServer/lmTool.ts +++ b/Extension/src/LanguageServer/lmTool.ts @@ -51,6 +51,7 @@ export class CppConfigurationLanguageModelTool implements vscode.LanguageModelTo } private async getContext(token: vscode.CancellationToken): Promise { + const telemetryProperties: Record = {}; try { const currentDoc = vscode.window.activeTextEditor?.document; if (!currentDoc || (!util.isCpp(currentDoc) && !util.isHeaderFile(currentDoc.uri))) { @@ -62,28 +63,44 @@ export class CppConfigurationLanguageModelTool implements vscode.LanguageModelTo return 'No configuration information is available for the active document.'; } - telemetry.logLanguageModelToolEvent( - 'cpp', - { - "language": chatContext.language, - "compiler": chatContext.compiler, - "standardVersion": chatContext.standardVersion, - "targetPlatform": chatContext.targetPlatform, - "targetArchitecture": chatContext.targetArchitecture - }); - for (const key in knownValues) { const knownKey = key as keyof ChatContextResult; if (knownValues[knownKey] && chatContext[knownKey]) { - chatContext[knownKey] = knownValues[knownKey][chatContext[knownKey]] || chatContext[knownKey]; + // Clear the value if it's not in the known values. + chatContext[knownKey] = knownValues[knownKey][chatContext[knownKey]] || ""; } } - return `The user is working on a ${chatContext.language} project. The project uses language version ${chatContext.standardVersion}, compiles using the ${chatContext.compiler} compiler, targets the ${chatContext.targetPlatform} platform, and targets the ${chatContext.targetArchitecture} architecture.`; + let contextString = ""; + if (chatContext.language) { + contextString += `The user is working on a ${chatContext.language} project. `; + telemetryProperties["language"] = chatContext.language; + } + if (chatContext.standardVersion) { + contextString += `The project uses language version ${chatContext.standardVersion}. `; + telemetryProperties["standardVersion"] = chatContext.standardVersion; + } + if (chatContext.compiler) { + contextString += `The project compiles using the ${chatContext.compiler} compiler. `; + telemetryProperties["compiler"] = chatContext.compiler; + } + if (chatContext.targetPlatform) { + contextString += `The project targets the ${chatContext.targetPlatform} platform. `; + telemetryProperties["targetPlatform"] = chatContext.targetPlatform; + } + if (chatContext.targetArchitecture) { + contextString += `The project targets the ${chatContext.targetArchitecture} architecture. `; + telemetryProperties["targetArchitecture"] = chatContext.targetArchitecture; + } + + return contextString; } catch { await this.reportError(); + telemetryProperties["error"] = "true"; return ""; + } finally { + telemetry.logLanguageModelToolEvent('cpp', telemetryProperties); } } diff --git a/Extension/src/LanguageServer/protocolFilter.ts b/Extension/src/LanguageServer/protocolFilter.ts index 4dddbbcc2..9829f0a13 100644 --- a/Extension/src/LanguageServer/protocolFilter.ts +++ b/Extension/src/LanguageServer/protocolFilter.ts @@ -15,17 +15,9 @@ import { shouldChangeFromCToCpp } from './utils'; export const RequestCancelled: number = -32800; export const ServerCancelled: number = -32802; -let anyFileOpened: boolean = false; - export function createProtocolFilter(): Middleware { - // Disabling lint for invoke handlers - const invoke1 = (a: any, next: (a: any) => any): any => clients.ActiveClient.enqueue(() => next(a)); - const invoke2 = (a: any, b: any, next: (a: any, b: any) => any): any => clients.ActiveClient.enqueue(() => next(a, b)); - const invoke3 = (a: any, b: any, c: any, next: (a: any, b: any, c: any) => any): any => clients.ActiveClient.enqueue(() => next(a, b, c)); - const invoke4 = (a: any, b: any, c: any, d: any, next: (a: any, b: any, c: any, d: any) => any): any => clients.ActiveClient.enqueue(() => next(a, b, c, d)); - return { - didOpen: async (document, sendMessage) => clients.ActiveClient.enqueue(async () => { + didOpen: async (document, sendMessage) => { if (!util.isCpp(document)) { return; } @@ -41,62 +33,32 @@ export function createProtocolFilter(): Middleware { const mappingString: string = baseFileName + "@" + document.fileName; client.addFileAssociations(mappingString, "cpp"); client.sendDidChangeSettings(); - document = await vscode.languages.setTextDocumentLanguage(document, "cpp"); + // This will cause the file to be closed and reopened. + void vscode.languages.setTextDocumentLanguage(document, "cpp"); + return; } // client.takeOwnership() will call client.TrackedDocuments.add() again, but that's ok. It's a Set. client.onDidOpenTextDocument(document); client.takeOwnership(document); - await sendMessage(document); - - // For a file already open when we activate, sometimes we don't get any notifications about visible - // or active text editors, visible ranges, or text selection. As a workaround, we trigger - // onDidChangeVisibleTextEditors here, only for the first file opened. - if (!anyFileOpened) { - anyFileOpened = true; - const cppEditors: vscode.TextEditor[] = vscode.window.visibleTextEditors.filter(e => util.isCpp(e.document)); - await client.onDidChangeVisibleTextEditors(cppEditors); - } + void sendMessage(document); } } - }), - didChange: invoke1, - willSave: invoke1, + }, willSaveWaitUntil: async (event, sendMessage) => { - // await clients.ActiveClient.ready; - // Don't use awaitUntilLanguageClientReady. - // Otherwise, the message can be delayed too long. const me: Client = clients.getClientFor(event.document.uri); if (me.TrackedDocuments.has(event.document.uri.toString())) { return sendMessage(event); } return []; }, - didSave: invoke1, - didClose: async (document, sendMessage) => clients.ActiveClient.enqueue(async () => { + didClose: async (document, sendMessage) => { const me: Client = clients.getClientFor(document.uri); const uriString: string = document.uri.toString(); if (me.TrackedDocuments.has(uriString)) { me.onDidCloseTextDocument(document); me.TrackedDocuments.delete(uriString); - await sendMessage(document); + void sendMessage(document); } - }), - provideCompletionItem: invoke4, - resolveCompletionItem: invoke2, - provideHover: async (document, position, token, next: (document: any, position: any, token: any) => any) => clients.ActiveClient.enqueue(async () => { - const me: Client = clients.getClientFor(document.uri); - if (me.TrackedDocuments.has(document.uri.toString())) { - return next(document, position, token); - } - return null; - }), - provideSignatureHelp: invoke4, - provideDefinition: invoke3, - provideReferences: invoke4, - provideDocumentHighlights: invoke3, - provideDeclaration: invoke3, - workspace: { - didChangeConfiguration: invoke1 } }; } diff --git a/Extension/src/common.ts b/Extension/src/common.ts index c962a719c..dbd0bcdd6 100644 --- a/Extension/src/common.ts +++ b/Extension/src/common.ts @@ -1814,3 +1814,7 @@ export function findExePathInArgs(args: CommandString[]): string | undefined { return undefined; } + +export function getVsCodeVersion(): number[] { + return vscode.version.split('.').map(num => parseInt(num, undefined)); +} diff --git a/Extension/yarn.lock b/Extension/yarn.lock index 7a59a937d..377974a1e 100644 --- a/Extension/yarn.lock +++ b/Extension/yarn.lock @@ -448,7 +448,7 @@ resolved "https://pkgs.dev.azure.com/azure-public/VisualCpp/_packaging/cpp_PublicPackages/npm/registry/@types/minimatch/-/minimatch-5.1.2.tgz#07508b45797cb81ec3f273011b054cd0755eddca" integrity sha1-B1CLRXl8uB7D8nMBGwVM0HVe3co= -"@types/minimatch@^3.0.3", "@types/minimatch@^3.0.5": +"@types/minimatch@^3.0.3": version "3.0.5" resolved "https://pkgs.dev.azure.com/azure-public/VisualCpp/_packaging/cpp_PublicPackages/npm/registry/@types/minimatch/-/minimatch-3.0.5.tgz#1001cc5e6a3704b83c236027e77f2f58ea010f40" integrity sha1-EAHMXmo3BLg8I2An538vWOoBD0A= @@ -3278,6 +3278,13 @@ minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: dependencies: brace-expansion "^1.1.7" +minimatch@^4.2.0: + version "4.2.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-4.2.3.tgz#b4dcece1d674dee104bb0fb833ebb85a78cbbca6" + integrity sha512-lIUdtK5hdofgCTu3aT0sOaHsYR37viUuIc0rwnnDXImbwFRcumyLMeZaM0t0I/fgxS6s6JMfu0rLD1Wz9pv1ng== + dependencies: + brace-expansion "^1.1.7" + minimatch@^5.0.1, minimatch@^5.1.0, minimatch@^5.1.6: version "5.1.6" resolved "https://pkgs.dev.azure.com/azure-public/VisualCpp/_packaging/cpp_PublicPackages/npm/registry/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96"