From 140872124584f6a1979d76e9af446bec798d0eb8 Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Wed, 22 Apr 2020 16:50:09 -0700 Subject: [PATCH 01/55] adding standard std version to clang_format_style --- Extension/package.nls.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Extension/package.nls.json b/Extension/package.nls.json index d7b17c9a7..897d9ce21 100644 --- a/Extension/package.nls.json +++ b/Extension/package.nls.json @@ -18,7 +18,7 @@ "c_cpp.command.vcpkgClipboardInstallSuggested.title": "Copy vcpkg install command to clipboard", "c_cpp.command.vcpkgOnlineHelpSuggested.title": "Visit the vcpkg help page", "c_cpp.configuration.clang_format_path.description": "The full path of the clang-format executable. If not specified, and clang-format is available in the environment path, that is used. If not found in the environment path, a copy of clang-format bundled with the extension will be used.", - "c_cpp.configuration.clang_format_style.description": "Coding style, currently supports: Visual Studio, LLVM, Google, Chromium, Mozilla, WebKit. Use \"file\" to load the style from a .clang-format file in the current or parent directory. Use {key: value, ...} to set specific parameters. For example, the \"Visual Studio\" style is similar to: { BasedOnStyle: LLVM, UseTab: Never, IndentWidth: 4, TabWidth: 4, BreakBeforeBraces: Allman, AllowShortIfStatementsOnASingleLine: false, IndentCaseLabels: false, ColumnLimit: 0, AccessModifierOffset: -4, NamespaceIndentation: All }", + "c_cpp.configuration.clang_format_style.description": "Coding style, currently supports: Visual Studio, LLVM, Google, Chromium, Mozilla, WebKit. Use \"file\" to load the style from a .clang-format file in the current or parent directory. Use {key: value, ...} to set specific parameters. For example, the \"Visual Studio\" style is similar to: { BasedOnStyle: LLVM, UseTab: Never, IndentWidth: 4, TabWidth: 4, BreakBeforeBraces: Allman, AllowShortIfStatementsOnASingleLine: false, IndentCaseLabels: false, ColumnLimit: 0, AccessModifierOffset: -4, NamespaceIndentation: All, Standard: Cpp03 }", "c_cpp.configuration.clang_format_fallbackStyle.description": "Name of the predefined style used as a fallback in case clang-format is invoked with style \"file\" but the .clang-format file is not found. Possible values are Visual Studio, LLVM, Google, Chromium, Mozilla, WebKit, none, or use {key: value, ...} to set specific parameters. For example, the \"Visual Studio\" style is similar to: { BasedOnStyle: LLVM, UseTab: Never, IndentWidth: 4, TabWidth: 4, BreakBeforeBraces: Allman, AllowShortIfStatementsOnASingleLine: false, IndentCaseLabels: false, ColumnLimit: 0, AccessModifierOffset: -4 }", "c_cpp.configuration.clang_format_sortIncludes.description": "If set, overrides the include sorting behavior determined by the SortIncludes parameter.", "c_cpp.configuration.intelliSenseEngine.description": "Controls the IntelliSense provider. \"Tag Parser\" provides \"fuzzy\" results that are not context-aware. \"Default\" provides context-aware results. \"Disabled\" turns off C/C++ language service features.", From 22368413bc835bc44c666862d74660da5ce7bed2 Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Wed, 3 Jun 2020 12:28:55 -0700 Subject: [PATCH 02/55] add new cppBuildTaskProvider --- .../src/Debugger/configurationProvider.ts | 4 +- .../LanguageServer/cppbuildTaskProvider.ts | 181 ++++++++++++++++++ Extension/src/LanguageServer/extension.ts | 12 +- Extension/src/common.ts | 3 +- 4 files changed, 195 insertions(+), 5 deletions(-) create mode 100644 Extension/src/LanguageServer/cppbuildTaskProvider.ts diff --git a/Extension/src/Debugger/configurationProvider.ts b/Extension/src/Debugger/configurationProvider.ts index 35ad0ce05..1aff5bad5 100644 --- a/Extension/src/Debugger/configurationProvider.ts +++ b/Extension/src/Debugger/configurationProvider.ts @@ -7,7 +7,8 @@ import * as debugUtils from './utils'; import * as os from 'os'; import * as path from 'path'; import * as vscode from 'vscode'; -import { getBuildTasks, BuildTaskDefinition } from '../LanguageServer/extension'; +import { BuildTaskDefinition } from '../LanguageServer/extension'; +import { CppBuildTaskProvider } from '../LanguageServer/cppbuildTaskProvider'; import * as util from '../common'; import * as fs from 'fs'; import * as Telemetry from '../telemetry'; @@ -106,6 +107,7 @@ class CppConfigurationProvider implements vscode.DebugConfigurationProvider { */ async provideDebugConfigurations(folder?: vscode.WorkspaceFolder, token?: vscode.CancellationToken): Promise { let buildTasks: vscode.Task[] = await getBuildTasks(true, true); + let buildTasks: vscode.Task[] = await new CppBuildTaskProvider().provideTasks(); if (buildTasks.length === 0) { return Promise.resolve(this.provider.getInitialConfigurations(this.type)); } diff --git a/Extension/src/LanguageServer/cppbuildTaskProvider.ts b/Extension/src/LanguageServer/cppbuildTaskProvider.ts new file mode 100644 index 000000000..e561d55ee --- /dev/null +++ b/Extension/src/LanguageServer/cppbuildTaskProvider.ts @@ -0,0 +1,181 @@ +/* -------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All Rights Reserved. + * See 'LICENSE' in the project root for license information. + * ------------------------------------------------------------------------------------------ */ +import * as path from 'path'; +import * as vscode from 'vscode'; +import * as os from 'os'; +import * as util from '../common'; +import * as telemetry from '../telemetry'; +import { Client } from './client'; +import * as configs from './configurations'; +import * as ext from './extension'; + +interface CppBuildTaskDefinition extends vscode.TaskDefinition { + type: string; // shell + label: string; + command: string; + args: string[]; + options: undefined | Record; +} + +export class CppBuildTaskProvider implements vscode.TaskProvider { + static CppBuildScriptType: string = 'cppbuild'; + private tasks: vscode.Task[] | undefined; + + constructor() {} + + public async provideTasks(): Promise { + return this.getTasks(); + } + + public resolveTask(_task: vscode.Task): vscode.Task | undefined { + // return this.getTask(compilerPath, compilerArgs); + const command: string = _task.definition.command; + if (command) { + const definition: CppBuildTaskDefinition = _task.definition; + return this.getTask(definition.command, definition.args ? definition.args : [], definition); + } + return undefined; + } + + // Generate tasks to build the current file based on the user's detected compilers, the user's compilerPath setting, and the current file's extension. + public async getTasks(): Promise { + this.tasks = []; + const editor: vscode.TextEditor | undefined = vscode.window.activeTextEditor; + if (!editor) { + return []; + } + + const fileExt: string = path.extname(editor.document.fileName); + if (!fileExt) { + return []; + } + + // Don't offer tasks for header files. + const fileExtLower: string = fileExt.toLowerCase(); + const isHeader: boolean = !fileExt || [".hpp", ".hh", ".hxx", ".h", ".inl", ""].some(ext => fileExtLower === ext); + if (isHeader) { + return []; + } + + // Don't offer tasks if the active file's extension is not a recognized C/C++ extension. + let fileIsCpp: boolean; + let fileIsC: boolean; + if (fileExt === ".C") { // ".C" file extensions are both C and C++. + fileIsCpp = true; + fileIsC = true; + } else { + fileIsCpp = [".cpp", ".cc", ".cxx", ".mm", ".ino"].some(ext => fileExtLower === ext); + fileIsC = fileExtLower === ".c"; + } + if (!(fileIsCpp || fileIsC)) { + return []; + } + + // Get compiler paths. + const isWindows: boolean = os.platform() === 'win32'; + let activeClient: Client; + try { + activeClient = ext.getActiveClient(); + } catch (e) { + if (!e || e.message !== ext.intelliSenseDisabledError) { + console.error("Unknown error calling getActiveClient()."); + } + return []; // Language service features may be disabled. + } + + // Get user compiler path. + const userCompilerPathAndArgs: util.CompilerPathAndArgs | undefined = await activeClient.getCurrentCompilerPathAndArgs(); + let userCompilerPath: string | undefined; + if (userCompilerPathAndArgs) { + userCompilerPath = userCompilerPathAndArgs.compilerPath; + if (userCompilerPath && userCompilerPathAndArgs.compilerName) { + userCompilerPath = userCompilerPath.trim(); + if (isWindows && userCompilerPath.startsWith("/")) { // TODO: Add WSL compiler support. + userCompilerPath = undefined; + } else { + userCompilerPath = userCompilerPath.replace(/\\\\/g, "\\"); + } + } + } + + // Get known compiler paths. Do not include the known compiler path that is the same as user compiler path. + // Filter them based on the file type to get a reduced list appropriate for the active file. + let knownCompilerPaths: string[] | undefined; + let knownCompilers: configs.KnownCompiler[] | undefined = await activeClient.getKnownCompilers(); + if (knownCompilers) { + knownCompilers = knownCompilers.filter(info => + ((fileIsCpp && !info.isC) || (fileIsC && info.isC)) && + userCompilerPathAndArgs && + (path.basename(info.path) !== userCompilerPathAndArgs.compilerName) && + (!isWindows || !info.path.startsWith("/"))); // TODO: Add WSL compiler support. + knownCompilerPaths = knownCompilers.map(info => info.path); + } + + if (!knownCompilerPaths && !userCompilerPath) { + // Don't prompt a message yet until we can make a data-based decision. + telemetry.logLanguageServerEvent('noCompilerFound'); + return []; + } + + // Create a build task per compiler path + + // Tasks for known compiler paths + if (knownCompilerPaths) { + this.tasks = knownCompilerPaths.map(compilerPath => this.getTask(compilerPath, undefined)); + } + + // Task for user compiler path setting + if (userCompilerPath) { + this.tasks.push(this.getTask(userCompilerPath, userCompilerPathAndArgs?.additionalArgs)); + } + + return this.tasks; + } + + private getTask: (compilerPath: string, compilerArgs?: string [], definition?: CppBuildTaskDefinition) => vscode.Task = (compilerPath: string, compilerArgs?: string [], definition?: CppBuildTaskDefinition) => { + + const filePath: string = path.join('${fileDirname}', '${fileBasenameNoExtension}'); + const compilerPathBase: string = path.basename(compilerPath); + const taskName: string = compilerPathBase + " build and debug active file"; + const isCl: boolean = compilerPathBase === "cl.exe"; + const isWindows: boolean = os.platform() === 'win32'; + const cwd: string = isCl ? "" : path.dirname(compilerPath); + let args: string[] = isCl ? ['/Zi', '/EHsc', '/Fe:', filePath + '.exe', '${file}'] : ['-g', '${file}', '-o', filePath + (isWindows ? '.exe' : '')]; + if (compilerArgs && compilerArgs.length > 0) { + args = args.concat(compilerArgs); + } + + let kind: CppBuildTaskDefinition = { + type: CppBuildTaskProvider.CppBuildScriptType, // shell + label: taskName, + command: isCl ? compilerPathBase : compilerPath, + args: args, + options: isCl ? undefined : {"cwd": cwd} + }; + + /* if (returnCompilerPath) { + kind = kind as CppBuildTaskDefinition; + kind.compilerPath = isCl ? compilerPathBase : compilerPath; + }*/ + + const command: vscode.ShellExecution = new vscode.ShellExecution(compilerPath, [...args], { cwd: cwd }); + let activeClient: Client = ext.getActiveClient(); + let uri: vscode.Uri | undefined = activeClient.RootUri; + if (!uri) { + throw new Error("No client URI found in getBuildTasks()"); + } + const target: vscode.WorkspaceFolder | undefined = vscode.workspace.getWorkspaceFolder(uri); + if (!target) { + throw new Error("No target WorkspaceFolder found in getBuildTasks()"); + } + let task: vscode.Task = new vscode.Task(kind, target, taskName, ext.taskSourceStr, command, isCl ? '$msCompile' : '$gcc'); + task.definition = kind; // The constructor for vscode.Task will consume the definition. Reset it by reassigning. + task.group = vscode.TaskGroup.Build; + + return task; + }; +} + + diff --git a/Extension/src/LanguageServer/extension.ts b/Extension/src/LanguageServer/extension.ts index a273222b7..3c901560f 100644 --- a/Extension/src/LanguageServer/extension.ts +++ b/Extension/src/LanguageServer/extension.ts @@ -22,13 +22,13 @@ import { PlatformInformation } from '../platform'; import { Range } from 'vscode-languageclient'; import { ChildProcess, spawn, execSync } from 'child_process'; import { getTargetBuildInfo, BuildInfo } from '../githubAPI'; -import * as configs from './configurations'; import { PackageVersion } from '../packageVersion'; import { getTemporaryCommandRegistrarInstance } from '../commands'; import * as rd from 'readline'; import * as yauzl from 'yauzl'; import { Readable, Writable } from 'stream'; import * as nls from 'vscode-nls'; +import { CppBuildTaskProvider } from './cppbuildTaskProvider'; nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })(); const localize: nls.LocalizeFunc = nls.loadMessageBundle(); @@ -49,10 +49,11 @@ let activatedPreviously: PersistentWorkspaceState; let buildInfoCache: BuildInfo | undefined; const taskTypeStr: string = "shell"; const taskSourceStr: string = "C/C++"; +export const taskSourceStr: string = "shell"; const cppInstallVsixStr: string = 'C/C++: Install vsix -- '; let taskProvider: vscode.Disposable; let codeActionProvider: vscode.Disposable; -const intelliSenseDisabledError: string = "Do not activate the extension when IntelliSense is disabled."; +export const intelliSenseDisabledError: string = "Do not activate the extension when IntelliSense is disabled."; type vcpkgDatabase = { [key: string]: string[] }; // Stored as
-> [] let vcpkgDbPromise: Promise; @@ -174,11 +175,16 @@ export function activate(activationEventOccurred: boolean): void { taskProvider = vscode.tasks.registerTaskProvider(taskTypeStr, { provideTasks: () => getBuildTasks(false, false), + /* taskProvidertaskProvider = vscode.tasks.registerTaskProvider(taskSourceStr, { + provideTasks: () => getBuildTasks(false), resolveTask(task: vscode.Task): vscode.Task | undefined { // Currently cannot implement because VS Code does not call this. Can implement custom output file directory when enabled. return undefined; } - }); + });*/ + + taskProvider = vscode.tasks.registerTaskProvider(CppBuildTaskProvider.CppBuildScriptType, new CppBuildTaskProvider()); + vscode.tasks.onDidStartTask(event => { if (event.execution.task.source === taskSourceStr) { telemetry.logLanguageServerEvent('buildTaskStarted'); diff --git a/Extension/src/common.ts b/Extension/src/common.ts index 5b9d06b6f..c130c7fc9 100644 --- a/Extension/src/common.ts +++ b/Extension/src/common.ts @@ -17,7 +17,7 @@ import * as assert from 'assert'; import * as https from 'https'; import * as tmp from 'tmp'; import { ClientRequest, OutgoingHttpHeaders } from 'http'; -import { getBuildTasks } from './LanguageServer/extension'; +import { CppBuildTaskProvider } from './LanguageServer/cppbuildTaskProvider'; import { OtherSettings } from './LanguageServer/settings'; import { lookupString } from './nativeStrings'; import * as nls from 'vscode-nls'; @@ -97,6 +97,7 @@ export async function ensureBuildTaskExists(taskName: string): Promise { } const buildTasks: vscode.Task[] = await getBuildTasks(false, true); + const buildTasks: vscode.Task[] = await new CppBuildTaskProvider().provideTasks(); selectedTask = buildTasks.find(task => task.name === taskName); console.assert(selectedTask); if (!selectedTask) { From ffc0b68701180fe150167af04b257a83ba044f8f Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Thu, 4 Jun 2020 10:19:37 -0700 Subject: [PATCH 03/55] add Sean's changes to tasks --- .../src/Debugger/configurationProvider.ts | 2 +- Extension/src/LanguageServer/extension.ts | 169 +----------------- Extension/src/common.ts | 2 +- 3 files changed, 6 insertions(+), 167 deletions(-) diff --git a/Extension/src/Debugger/configurationProvider.ts b/Extension/src/Debugger/configurationProvider.ts index 1aff5bad5..16edca67e 100644 --- a/Extension/src/Debugger/configurationProvider.ts +++ b/Extension/src/Debugger/configurationProvider.ts @@ -106,7 +106,7 @@ class CppConfigurationProvider implements vscode.DebugConfigurationProvider { * Returns a list of initial debug configurations based on contextual information, e.g. package.json or folder. */ async provideDebugConfigurations(folder?: vscode.WorkspaceFolder, token?: vscode.CancellationToken): Promise { - let buildTasks: vscode.Task[] = await getBuildTasks(true, true); + // let buildTasks: vscode.Task[] = await getBuildTasks(true, true); let buildTasks: vscode.Task[] = await new CppBuildTaskProvider().provideTasks(); if (buildTasks.length === 0) { return Promise.resolve(this.provider.getInitialConfigurations(this.type)); diff --git a/Extension/src/LanguageServer/extension.ts b/Extension/src/LanguageServer/extension.ts index 3c901560f..fd348a3ca 100644 --- a/Extension/src/LanguageServer/extension.ts +++ b/Extension/src/LanguageServer/extension.ts @@ -47,9 +47,9 @@ let realActivationOccurred: boolean = false; let tempCommands: vscode.Disposable[] = []; let activatedPreviously: PersistentWorkspaceState; let buildInfoCache: BuildInfo | undefined; -const taskTypeStr: string = "shell"; -const taskSourceStr: string = "C/C++"; -export const taskSourceStr: string = "shell"; +// const taskTypeStr: string = "shell"; +export const taskSourceStr: string = "C/C++"; +// export const taskSourceStr: string = "shell"; const cppInstallVsixStr: string = 'C/C++: Install vsix -- '; let taskProvider: vscode.Disposable; let codeActionProvider: vscode.Disposable; @@ -173,10 +173,8 @@ export function activate(activationEventOccurred: boolean): void { return; } - taskProvider = vscode.tasks.registerTaskProvider(taskTypeStr, { + /* taskProvidertaskProvider = vscode.tasks.registerTaskProvider(taskTypeStr, { provideTasks: () => getBuildTasks(false, false), - /* taskProvidertaskProvider = vscode.tasks.registerTaskProvider(taskSourceStr, { - provideTasks: () => getBuildTasks(false), resolveTask(task: vscode.Task): vscode.Task | undefined { // Currently cannot implement because VS Code does not call this. Can implement custom output file directory when enabled. return undefined; @@ -247,165 +245,6 @@ export interface BuildTaskDefinition extends vscode.TaskDefinition { compilerPath: string; } -/** - * Generate tasks to build the current file based on the user's detected compilers, the user's compilerPath setting, and the current file's extension. - */ -export async function getBuildTasks(returnCompilerPath: boolean, appendSourceToName: boolean): Promise { - const editor: vscode.TextEditor | undefined = vscode.window.activeTextEditor; - if (!editor) { - return []; - } - - const fileExt: string = path.extname(editor.document.fileName); - if (!fileExt) { - return []; - } - - // Don't offer tasks for header files. - const fileExtLower: string = fileExt.toLowerCase(); - const isHeader: boolean = !fileExt || [".hpp", ".hh", ".hxx", ".h", ".inl", ""].some(ext => fileExtLower === ext); - if (isHeader) { - return []; - } - - // Don't offer tasks if the active file's extension is not a recognized C/C++ extension. - let fileIsCpp: boolean; - let fileIsC: boolean; - if (fileExt === ".C") { // ".C" file extensions are both C and C++. - fileIsCpp = true; - fileIsC = true; - } else { - fileIsCpp = [".cpp", ".cc", ".cxx", ".mm", ".ino"].some(ext => fileExtLower === ext); - fileIsC = fileExtLower === ".c"; - } - if (!(fileIsCpp || fileIsC)) { - return []; - } - - // Get compiler paths. - const isWindows: boolean = os.platform() === 'win32'; - let activeClient: Client; - try { - activeClient = getActiveClient(); - } catch (e) { - if (!e || e.message !== intelliSenseDisabledError) { - console.error("Unknown error calling getActiveClient()."); - } - return []; // Language service features may be disabled. - } - - // Get user compiler path. - const userCompilerPathAndArgs: util.CompilerPathAndArgs | undefined = await activeClient.getCurrentCompilerPathAndArgs(); - let userCompilerPath: string | undefined; - if (userCompilerPathAndArgs) { - userCompilerPath = userCompilerPathAndArgs.compilerPath; - if (userCompilerPath && userCompilerPathAndArgs.compilerName) { - userCompilerPath = userCompilerPath.trim(); - if (isWindows && userCompilerPath.startsWith("/")) { // TODO: Add WSL compiler support. - userCompilerPath = undefined; - } else { - userCompilerPath = userCompilerPath.replace(/\\\\/g, "\\"); - } - } - } - - // Get known compiler paths. Do not include the known compiler path that is the same as user compiler path. - // Filter them based on the file type to get a reduced list appropriate for the active file. - let knownCompilerPaths: string[] | undefined; - let knownCompilers: configs.KnownCompiler[] | undefined = await activeClient.getKnownCompilers(); - if (knownCompilers) { - knownCompilers = knownCompilers.filter(info => - ((fileIsCpp && !info.isC) || (fileIsC && info.isC)) && - userCompilerPathAndArgs && - (path.basename(info.path) !== userCompilerPathAndArgs.compilerName) && - (!isWindows || !info.path.startsWith("/"))); // TODO: Add WSL compiler support. - knownCompilerPaths = knownCompilers.map(info => info.path); - } - - if (!knownCompilerPaths && !userCompilerPath) { - // Don't prompt a message yet until we can make a data-based decision. - telemetry.logLanguageServerEvent('noCompilerFound'); - // Display a message prompting the user to install compilers if none were found. - // const dontShowAgain: string = "Don't Show Again"; - // const learnMore: string = "Learn More"; - // const message: string = "No C/C++ compiler found on the system. Please install a C/C++ compiler to use the C/C++: build active file tasks."; - - // let showNoCompilerFoundMessage: PersistentState = new PersistentState("CPP.showNoCompilerFoundMessage", true); - // if (showNoCompilerFoundMessage) { - // vscode.window.showInformationMessage(message, learnMore, dontShowAgain).then(selection => { - // switch (selection) { - // case learnMore: - // const uri: vscode.Uri = vscode.Uri.parse(`https://go.microsoft.com/fwlink/?linkid=864631`); - // vscode.commands.executeCommand('vscode.open', uri); - // break; - // case dontShowAgain: - // showNoCompilerFoundMessage.Value = false; - // break; - // default: - // break; - // } - // }); - // } - return []; - } - - let createTask: (compilerPath: string, compilerArgs?: string []) => vscode.Task = (compilerPath: string, compilerArgs?: string []) => { - const filePath: string = path.join('${fileDirname}', '${fileBasenameNoExtension}'); - const compilerPathBase: string = path.basename(compilerPath); - const taskName: string = (appendSourceToName ? taskSourceStr + ": " : "") + compilerPathBase + " build active file"; - const isCl: boolean = compilerPathBase === "cl.exe"; - const cwd: string = "${workspaceFolder}"; - let args: string[] = isCl ? ['/Zi', '/EHsc', '/Fe:', filePath + '.exe', '${file}'] : ['-g', '${file}', '-o', filePath + (isWindows ? '.exe' : '')]; - if (compilerArgs && compilerArgs.length > 0) { - args = args.concat(compilerArgs); - } - - let kind: vscode.TaskDefinition = { - type: taskTypeStr, - label: taskName, - command: isCl ? compilerPathBase : compilerPath, - args: args, - options: { "cwd": cwd } - }; - - if (returnCompilerPath) { - kind = kind as BuildTaskDefinition; - kind.compilerPath = isCl ? compilerPathBase : compilerPath; - } - - const command: vscode.ShellExecution = new vscode.ShellExecution(compilerPath, [...args], { cwd: cwd }); - let uri: vscode.Uri | undefined = clients.ActiveClient.RootUri; - if (!uri) { - throw new Error("No client URI found in getBuildTasks()"); - } - const target: vscode.WorkspaceFolder | undefined = vscode.workspace.getWorkspaceFolder(uri); - if (!target) { - throw new Error("No target WorkspaceFolder found in getBuildTasks()"); - } - let task: vscode.Task = new vscode.Task(kind, target, taskName, taskSourceStr, command, isCl ? '$msCompile' : '$gcc'); - task.definition = kind; // The constructor for vscode.Task will consume the definition. Reset it by reassigning. - task.group = vscode.TaskGroup.Build; - - return task; - }; - - // Create a build task per compiler path - let buildTasks: vscode.Task[] = []; - - // Tasks for known compiler paths - if (knownCompilerPaths) { - buildTasks = knownCompilerPaths.map(compilerPath => createTask(compilerPath, undefined)); - } - - // Task for user compiler path setting - if (userCompilerPath) { - let task: vscode.Task = createTask(userCompilerPath, userCompilerPathAndArgs?.additionalArgs); - buildTasks.push(task); - } - - return buildTasks; -} - function onDidOpenTextDocument(document: vscode.TextDocument): void { if (document.languageId === "c" || document.languageId === "cpp") { onActivationEvent(); diff --git a/Extension/src/common.ts b/Extension/src/common.ts index c130c7fc9..3b541918f 100644 --- a/Extension/src/common.ts +++ b/Extension/src/common.ts @@ -96,7 +96,7 @@ export async function ensureBuildTaskExists(taskName: string): Promise { return; } - const buildTasks: vscode.Task[] = await getBuildTasks(false, true); + // const buildTasks: vscode.Task[] = await getBuildTasks(false, true); const buildTasks: vscode.Task[] = await new CppBuildTaskProvider().provideTasks(); selectedTask = buildTasks.find(task => task.name === taskName); console.assert(selectedTask); From e8eecd948e956b6464ff72d677a50892c0311990 Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Wed, 10 Jun 2020 16:45:40 -0700 Subject: [PATCH 04/55] draft --- Extension/package.json | 28 ++++- .../src/Debugger/configurationProvider.ts | 8 +- .../LanguageServer/cppbuildTaskProvider.ts | 107 ++++++++++++++---- Extension/src/LanguageServer/extension.ts | 17 +-- Extension/src/common.ts | 3 +- 5 files changed, 116 insertions(+), 47 deletions(-) diff --git a/Extension/package.json b/Extension/package.json index 3db166950..8f0f56042 100644 --- a/Extension/package.json +++ b/Extension/package.json @@ -12,7 +12,7 @@ }, "license": "SEE LICENSE IN LICENSE.txt", "engines": { - "vscode": "^1.43.0" + "vscode": "^1.44.0" }, "bugs": { "url": "https://github.com/Microsoft/vscode-cpptools/issues", @@ -43,6 +43,32 @@ ], "main": "./dist/main", "contributes": { + "taskDefinitions": [ + { + "type": "cppbuild", + "required": [ + "command" + ], + "properties": { + "label": { + "type": "string", + "description": "Task's name." + }, + "command": { + "type": "string", + "description": "The compiler path." + }, + "flags": { + "type": "array", + "description": "Additional build flags." + }, + "options": { + "type": "object", + "description": "Current working directory." + } + } + } + ], "views": { "references-view": [ { diff --git a/Extension/src/Debugger/configurationProvider.ts b/Extension/src/Debugger/configurationProvider.ts index 16edca67e..2d8943896 100644 --- a/Extension/src/Debugger/configurationProvider.ts +++ b/Extension/src/Debugger/configurationProvider.ts @@ -7,8 +7,7 @@ import * as debugUtils from './utils'; import * as os from 'os'; import * as path from 'path'; import * as vscode from 'vscode'; -import { BuildTaskDefinition } from '../LanguageServer/extension'; -import { CppBuildTaskProvider } from '../LanguageServer/cppbuildTaskProvider'; +import { CppBuildTaskProvider, CppBuildTaskDefinition} from '../LanguageServer/cppbuildTaskProvider'; import * as util from '../common'; import * as fs from 'fs'; import * as Telemetry from '../telemetry'; @@ -106,8 +105,7 @@ class CppConfigurationProvider implements vscode.DebugConfigurationProvider { * Returns a list of initial debug configurations based on contextual information, e.g. package.json or folder. */ async provideDebugConfigurations(folder?: vscode.WorkspaceFolder, token?: vscode.CancellationToken): Promise { - // let buildTasks: vscode.Task[] = await getBuildTasks(true, true); - let buildTasks: vscode.Task[] = await new CppBuildTaskProvider().provideTasks(); + let buildTasks: vscode.Task[] = await new CppBuildTaskProvider().getTasks(true, true); if (buildTasks.length === 0) { return Promise.resolve(this.provider.getInitialConfigurations(this.type)); } @@ -135,7 +133,7 @@ class CppConfigurationProvider implements vscode.DebugConfigurationProvider { // Generate new configurations for each build task. // Generating a task is async, therefore we must *await* *all* map(task => config) Promises to resolve. let configs: vscode.DebugConfiguration[] = await Promise.all(buildTasks.map>(async task => { - const definition: BuildTaskDefinition = task.definition as BuildTaskDefinition; + const definition: CppBuildTaskDefinition = task.definition as CppBuildTaskDefinition; const compilerName: string = path.basename(definition.compilerPath); let newConfig: vscode.DebugConfiguration = {...defaultConfig}; // Copy enumerables and properties diff --git a/Extension/src/LanguageServer/cppbuildTaskProvider.ts b/Extension/src/LanguageServer/cppbuildTaskProvider.ts index e561d55ee..b5d24d900 100644 --- a/Extension/src/LanguageServer/cppbuildTaskProvider.ts +++ b/Extension/src/LanguageServer/cppbuildTaskProvider.ts @@ -10,9 +10,11 @@ import * as telemetry from '../telemetry'; import { Client } from './client'; import * as configs from './configurations'; import * as ext from './extension'; +import { exec } from "child_process"; -interface CppBuildTaskDefinition extends vscode.TaskDefinition { - type: string; // shell + +export interface CppBuildTaskDefinition extends vscode.TaskDefinition { + type: string; label: string; command: string; args: string[]; @@ -21,12 +23,13 @@ interface CppBuildTaskDefinition extends vscode.TaskDefinition { export class CppBuildTaskProvider implements vscode.TaskProvider { static CppBuildScriptType: string = 'cppbuild'; + static CppBuildSourceStr: string = "C/C++"; private tasks: vscode.Task[] | undefined; constructor() {} public async provideTasks(): Promise { - return this.getTasks(); + return this.getTasks(false, false); } public resolveTask(_task: vscode.Task): vscode.Task | undefined { @@ -34,13 +37,13 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { const command: string = _task.definition.command; if (command) { const definition: CppBuildTaskDefinition = _task.definition; - return this.getTask(definition.command, definition.args ? definition.args : [], definition); + return this.getTask(definition.command, false, false, definition.args ? definition.args : [], definition); } return undefined; } // Generate tasks to build the current file based on the user's detected compilers, the user's compilerPath setting, and the current file's extension. - public async getTasks(): Promise { + public async getTasks(returnCompilerPath: boolean, appendSourceToName: boolean): Promise { this.tasks = []; const editor: vscode.TextEditor | undefined = vscode.window.activeTextEditor; if (!editor) { @@ -123,22 +126,22 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { // Tasks for known compiler paths if (knownCompilerPaths) { - this.tasks = knownCompilerPaths.map(compilerPath => this.getTask(compilerPath, undefined)); + this.tasks = knownCompilerPaths.map(compilerPath => this.getTask(compilerPath, returnCompilerPath, appendSourceToName, undefined)); } // Task for user compiler path setting if (userCompilerPath) { - this.tasks.push(this.getTask(userCompilerPath, userCompilerPathAndArgs?.additionalArgs)); + this.tasks.push(this.getTask(userCompilerPath, returnCompilerPath, appendSourceToName, userCompilerPathAndArgs?.additionalArgs)); } return this.tasks; } - private getTask: (compilerPath: string, compilerArgs?: string [], definition?: CppBuildTaskDefinition) => vscode.Task = (compilerPath: string, compilerArgs?: string [], definition?: CppBuildTaskDefinition) => { + private getTask: (compilerPath: string, returnCompilerPath: boolean, appendSourceToName: boolean, compilerArgs?: string [], definition?: CppBuildTaskDefinition) => vscode.Task = (compilerPath: string, returnCompilerPath: boolean, appendSourceToName: boolean, compilerArgs?: string [], definition?: CppBuildTaskDefinition) => { const filePath: string = path.join('${fileDirname}', '${fileBasenameNoExtension}'); const compilerPathBase: string = path.basename(compilerPath); - const taskName: string = compilerPathBase + " build and debug active file"; + const taskName: string = (appendSourceToName ? CppBuildTaskProvider.CppBuildSourceStr + ": " : "") + compilerPathBase + " build active file"; const isCl: boolean = compilerPathBase === "cl.exe"; const isWindows: boolean = os.platform() === 'win32'; const cwd: string = isCl ? "" : path.dirname(compilerPath); @@ -147,20 +150,23 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { args = args.concat(compilerArgs); } - let kind: CppBuildTaskDefinition = { - type: CppBuildTaskProvider.CppBuildScriptType, // shell - label: taskName, - command: isCl ? compilerPathBase : compilerPath, - args: args, - options: isCl ? undefined : {"cwd": cwd} - }; + if (definition === undefined) { + definition = { + type: CppBuildTaskProvider.CppBuildScriptType, + label: taskName, + command: isCl ? compilerPathBase : compilerPath, + args: args, + options: isCl ? undefined : {"cwd": cwd} + }; + } - /* if (returnCompilerPath) { - kind = kind as CppBuildTaskDefinition; - kind.compilerPath = isCl ? compilerPathBase : compilerPath; - }*/ + if (returnCompilerPath) { + definition = definition as CppBuildTaskDefinition; + definition.compilerPath = isCl ? compilerPathBase : compilerPath; + } - const command: vscode.ShellExecution = new vscode.ShellExecution(compilerPath, [...args], { cwd: cwd }); + // const command: vscode.ShellExecution = new vscode.ShellExecution(compilerPath, [...args], { cwd: cwd }); + const command: string = compilerPath + args.join(" "); let activeClient: Client = ext.getActiveClient(); let uri: vscode.Uri | undefined = activeClient.RootUri; if (!uri) { @@ -170,12 +176,67 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { if (!target) { throw new Error("No target WorkspaceFolder found in getBuildTasks()"); } - let task: vscode.Task = new vscode.Task(kind, target, taskName, ext.taskSourceStr, command, isCl ? '$msCompile' : '$gcc'); - task.definition = kind; // The constructor for vscode.Task will consume the definition. Reset it by reassigning. + + let task: vscode.Task = new vscode.Task(definition, target, taskName, CppBuildTaskProvider.CppBuildSourceStr, + new vscode.CustomExecution(async (): Promise => + // When the task is executed, this callback will run. Here, we setup for running the task. + new CustomBuildTaskTerminal(command) + ), isCl ? '$msCompile' : '$gcc'); + + /* let task: vscode.Task = new vscode.Task(definition, target, taskName, CppBuildTaskProvider.CppBuildSourceStr, + command, isCl ? '$msCompile' : '$gcc');*/ task.group = vscode.TaskGroup.Build; return task; }; } +class CustomBuildTaskTerminal implements vscode.Pseudoterminal { + private writeEmitter = new vscode.EventEmitter(); + // eslint-disable-next-line no-invalid-this + onDidWrite: vscode.Event = this.writeEmitter.event; + private closeEmitter = new vscode.EventEmitter(); + // eslint-disable-next-line no-invalid-this + onDidClose?: vscode.Event = this.closeEmitter.event; + + private fileWatcher: vscode.FileSystemWatcher | undefined; + + private shellCommand: string; + + constructor(command: string) { + this.shellCommand = command; + } + + open(initialDimensions: vscode.TerminalDimensions | undefined): void { + telemetry.logLanguageServerEvent('cppBuildTaskStarted'); + // At this point we can start using the terminal. + this.writeEmitter.fire('Starting build...\r\n'); + this.doBuild(); + } + + close(): void { + // The terminal has been closed. Shutdown the build. + if (this.fileWatcher) { + this.fileWatcher.dispose(); + } + } + + private async doBuild(): Promise { + return new Promise((resolve) => { + // build + exec(this.shellCommand, (_error, stdout, stderr) => { + this.writeEmitter.fire(stdout); + this.writeEmitter.fire(stderr); + if (stderr) { + telemetry.logLanguageServerEvent('cppBuildTaskError'); + this.writeEmitter.fire('Build finished with error.\r\n'); + } else { + this.writeEmitter.fire('Build finished successfully.\r\n'); + } + }); + this.closeEmitter.fire(); + }); + + } +} diff --git a/Extension/src/LanguageServer/extension.ts b/Extension/src/LanguageServer/extension.ts index fd348a3ca..751da7fd7 100644 --- a/Extension/src/LanguageServer/extension.ts +++ b/Extension/src/LanguageServer/extension.ts @@ -47,9 +47,6 @@ let realActivationOccurred: boolean = false; let tempCommands: vscode.Disposable[] = []; let activatedPreviously: PersistentWorkspaceState; let buildInfoCache: BuildInfo | undefined; -// const taskTypeStr: string = "shell"; -export const taskSourceStr: string = "C/C++"; -// export const taskSourceStr: string = "shell"; const cppInstallVsixStr: string = 'C/C++: Install vsix -- '; let taskProvider: vscode.Disposable; let codeActionProvider: vscode.Disposable; @@ -173,18 +170,10 @@ export function activate(activationEventOccurred: boolean): void { return; } - /* taskProvidertaskProvider = vscode.tasks.registerTaskProvider(taskTypeStr, { - provideTasks: () => getBuildTasks(false, false), - resolveTask(task: vscode.Task): vscode.Task | undefined { - // Currently cannot implement because VS Code does not call this. Can implement custom output file directory when enabled. - return undefined; - } - });*/ - taskProvider = vscode.tasks.registerTaskProvider(CppBuildTaskProvider.CppBuildScriptType, new CppBuildTaskProvider()); vscode.tasks.onDidStartTask(event => { - if (event.execution.task.source === taskSourceStr) { + if (event.execution.task.source === CppBuildTaskProvider.CppBuildSourceStr) { telemetry.logLanguageServerEvent('buildTaskStarted'); } }); @@ -241,10 +230,6 @@ export function activate(activationEventOccurred: boolean): void { } } -export interface BuildTaskDefinition extends vscode.TaskDefinition { - compilerPath: string; -} - function onDidOpenTextDocument(document: vscode.TextDocument): void { if (document.languageId === "c" || document.languageId === "cpp") { onActivationEvent(); diff --git a/Extension/src/common.ts b/Extension/src/common.ts index 3b541918f..40dd9a18b 100644 --- a/Extension/src/common.ts +++ b/Extension/src/common.ts @@ -96,8 +96,7 @@ export async function ensureBuildTaskExists(taskName: string): Promise { return; } - // const buildTasks: vscode.Task[] = await getBuildTasks(false, true); - const buildTasks: vscode.Task[] = await new CppBuildTaskProvider().provideTasks(); + const buildTasks: vscode.Task[] = await new CppBuildTaskProvider().getTasks(false, true); selectedTask = buildTasks.find(task => task.name === taskName); console.assert(selectedTask); if (!selectedTask) { From e8d58aa98d30288579744e8364b1021da5f216b6 Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Thu, 11 Jun 2020 17:24:26 -0700 Subject: [PATCH 05/55] draft 2 --- .../LanguageServer/cppbuildTaskProvider.ts | 44 ++++++++++++++----- Extension/src/common.ts | 22 +++++++++- 2 files changed, 55 insertions(+), 11 deletions(-) diff --git a/Extension/src/LanguageServer/cppbuildTaskProvider.ts b/Extension/src/LanguageServer/cppbuildTaskProvider.ts index b5d24d900..3c2c6ca9b 100644 --- a/Extension/src/LanguageServer/cppbuildTaskProvider.ts +++ b/Extension/src/LanguageServer/cppbuildTaskProvider.ts @@ -201,17 +201,17 @@ class CustomBuildTaskTerminal implements vscode.Pseudoterminal { private fileWatcher: vscode.FileSystemWatcher | undefined; - private shellCommand: string; + private command: string; constructor(command: string) { - this.shellCommand = command; + this.command = command; } open(initialDimensions: vscode.TerminalDimensions | undefined): void { - telemetry.logLanguageServerEvent('cppBuildTaskStarted'); + telemetry.logLanguageServerEvent("cppBuildTaskStarted"); // At this point we can start using the terminal. - this.writeEmitter.fire('Starting build...\r\n'); + this.writeEmitter.fire("Starting build...\r\n"); this.doBuild(); } @@ -224,19 +224,43 @@ class CustomBuildTaskTerminal implements vscode.Pseudoterminal { private async doBuild(): Promise { return new Promise((resolve) => { - // build - exec(this.shellCommand, (_error, stdout, stderr) => { + // Do build. + const activeCommand: string = this.resolveCommand(this.command); + exec("echo \"...\""); + exec(activeCommand, (_error, stdout, stderr) => { this.writeEmitter.fire(stdout); this.writeEmitter.fire(stderr); - if (stderr) { - telemetry.logLanguageServerEvent('cppBuildTaskError'); - this.writeEmitter.fire('Build finished with error.\r\n'); + if (_error) { + telemetry.logLanguageServerEvent("cppBuildTaskError"); + this.writeEmitter.fire("Build finished with error.\r\n"); } else { - this.writeEmitter.fire('Build finished successfully.\r\n'); + this.writeEmitter.fire("Build finished successfully.\r\n"); } }); + // Set timeout to give enough time to the writeEmitter to print all messages. + setTimeout(() => {resolve(); }, 1000); this.closeEmitter.fire(); }); } + + private resolveCommand(command: string): string { + + let result: string = ""; + // first resolve variables + result = util.resolveVariables(command); + let file: string | undefined = vscode.window.activeTextEditor?.document.uri.fsPath; + if (file) { + if (result.includes("${file}")) { + result = result.replace("${file}", file); + } + if (result.includes("${fileDirname}")) { + result = result.replace("${fileDirname}", path.dirname(file)); + } + if (result.includes("${fileBasenameNoExtension}")) { + result = result.replace("${fileBasenameNoExtension}", path.parse(file).name); + } + } + return result; + } } diff --git a/Extension/src/common.ts b/Extension/src/common.ts index 40dd9a18b..8623bb655 100644 --- a/Extension/src/common.ts +++ b/Extension/src/common.ts @@ -344,7 +344,7 @@ export function resolveVariables(input: string | undefined, additionalEnvironmen } // Replace environment and configuration variables. - let regexp: () => RegExp = () => /\$\{((env|config|workspaceFolder)(\.|:))?(.*?)\}/g; + let regexp: () => RegExp = () => /\$\{((env|config|workspaceFolder|file|fileDirname|fileBasenameNoExtension)(\.|:))?(.*?)\}/g; let ret: string = input; let cycleCache: Set = new Set(); while (!cycleCache.has(ret)) { @@ -390,6 +390,26 @@ export function resolveVariables(input: string | undefined, additionalEnvironmen } break; } + case "file": { + newValue = vscode.window.activeTextEditor?.document.uri.toString(); + break; + } + case "fileDirname": { + if (name && vscode.workspace && vscode.workspace.workspaceFolders) { + let folder: vscode.WorkspaceFolder | undefined = vscode.workspace.workspaceFolders.find(folder => folder.name.toLocaleLowerCase() === name.toLocaleLowerCase()); + if (folder) { + newValue = folder.uri.fsPath; + } + } + break; + } + case "fileBasenameNoExtension": { + let fileBaseName: string | undefined = vscode.window.activeTextEditor?.document.uri.toString(); + if (fileBaseName) { + newValue = path.parse(fileBaseName).name; + } + break; + } default: { assert.fail("unknown varType matched"); } } return newValue !== undefined ? newValue : match; From d3c898a409f9aead3669875ce5c182fcf6d53579 Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Fri, 12 Jun 2020 14:48:31 -0700 Subject: [PATCH 06/55] draft 3 - working --- Extension/src/Debugger/extension.ts | 5 +- .../LanguageServer/cppbuildTaskProvider.ts | 87 +++++++++++++------ Extension/src/common.ts | 58 +------------ 3 files changed, 66 insertions(+), 84 deletions(-) diff --git a/Extension/src/Debugger/extension.ts b/Extension/src/Debugger/extension.ts index c897b04cc..41a2c6b87 100644 --- a/Extension/src/Debugger/extension.ts +++ b/Extension/src/Debugger/extension.ts @@ -9,6 +9,7 @@ import { AttachPicker, RemoteAttachPicker, AttachItemsProvider } from './attachT import { NativeAttachItemsProviderFactory } from './nativeAttach'; import { QuickPickConfigurationProvider, ConfigurationAssetProviderFactory, CppVsDbgConfigurationProvider, CppDbgConfigurationProvider, ConfigurationSnippetProvider, IConfigurationAssetProvider } from './configurationProvider'; import { CppdbgDebugAdapterDescriptorFactory, CppvsdbgDebugAdapterDescriptorFactory } from './debugAdapterDescriptorFactory'; +import { failedToParseTasksJson } from '../LanguageServer/cppbuildTaskProvider'; import * as util from '../common'; import * as Telemetry from '../telemetry'; import * as nls from 'vscode-nls'; @@ -91,8 +92,8 @@ export function initialize(context: vscode.ExtensionContext): void { await util.ensureBuildTaskExists(selection.configuration.preLaunchTask); Telemetry.logDebuggerEvent("buildAndDebug", { "success": "false" }); } catch (e) { - if (e && e.message === util.failedToParseTasksJson) { - vscode.window.showErrorMessage(util.failedToParseTasksJson); + if (e && e.message === failedToParseTasksJson) { + vscode.window.showErrorMessage(failedToParseTasksJson); } return Promise.resolve(); } diff --git a/Extension/src/LanguageServer/cppbuildTaskProvider.ts b/Extension/src/LanguageServer/cppbuildTaskProvider.ts index 3c2c6ca9b..7a910d36b 100644 --- a/Extension/src/LanguageServer/cppbuildTaskProvider.ts +++ b/Extension/src/LanguageServer/cppbuildTaskProvider.ts @@ -10,8 +10,12 @@ import * as telemetry from '../telemetry'; import { Client } from './client'; import * as configs from './configurations'; import * as ext from './extension'; +import * as fs from 'fs'; +import * as nls from 'vscode-nls'; import { exec } from "child_process"; +const localize: nls.LocalizeFunc = nls.loadMessageBundle(); +export const failedToParseTasksJson: string = localize("failed.to.parse.tasks", "Failed to parse tasks.json, possibly due to comments or trailing commas."); export interface CppBuildTaskDefinition extends vscode.TaskDefinition { type: string; @@ -150,11 +154,18 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { args = args.concat(compilerArgs); } + // Double-quote the command if it is not already double-quoted. + let resolvedcompilerPath: string = isCl ? compilerPathBase : compilerPath; + if (resolvedcompilerPath && !resolvedcompilerPath.startsWith("\"")) { + resolvedcompilerPath = "\"" + resolvedcompilerPath + "\""; + } + const command: string = resolvedcompilerPath + " " + args.join(" "); + if (definition === undefined) { definition = { type: CppBuildTaskProvider.CppBuildScriptType, label: taskName, - command: isCl ? compilerPathBase : compilerPath, + command: command, args: args, options: isCl ? undefined : {"cwd": cwd} }; @@ -165,8 +176,6 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { definition.compilerPath = isCl ? compilerPathBase : compilerPath; } - // const command: vscode.ShellExecution = new vscode.ShellExecution(compilerPath, [...args], { cwd: cwd }); - const command: string = compilerPath + args.join(" "); let activeClient: Client = ext.getActiveClient(); let uri: vscode.Uri | undefined = activeClient.RootUri; if (!uri) { @@ -183,8 +192,9 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { new CustomBuildTaskTerminal(command) ), isCl ? '$msCompile' : '$gcc'); - /* let task: vscode.Task = new vscode.Task(definition, target, taskName, CppBuildTaskProvider.CppBuildSourceStr, - command, isCl ? '$msCompile' : '$gcc');*/ + /* const normalcommand: vscode.ShellExecution = new vscode.ShellExecution(compilerPath, [...args], { cwd: cwd }); + let task: vscode.Task = new vscode.Task(definition, target, taskName, CppBuildTaskProvider.CppBuildSourceStr, + normalcommand, isCl ? '$msCompile' : '$gcc');*/ task.group = vscode.TaskGroup.Build; return task; @@ -225,8 +235,7 @@ class CustomBuildTaskTerminal implements vscode.Pseudoterminal { private async doBuild(): Promise { return new Promise((resolve) => { // Do build. - const activeCommand: string = this.resolveCommand(this.command); - exec("echo \"...\""); + const activeCommand: string = util.resolveVariables(this.command, this.AdditionalEnvironment); exec(activeCommand, (_error, stdout, stderr) => { this.writeEmitter.fire(stdout); this.writeEmitter.fire(stderr); @@ -237,30 +246,58 @@ class CustomBuildTaskTerminal implements vscode.Pseudoterminal { this.writeEmitter.fire("Build finished successfully.\r\n"); } }); + this.writeEmitter.fire("\r\n"); // Set timeout to give enough time to the writeEmitter to print all messages. - setTimeout(() => {resolve(); }, 1000); - this.closeEmitter.fire(); + setTimeout(() => {this.closeEmitter.fire(); }, 3000); }); - } - private resolveCommand(command: string): string { + private get AdditionalEnvironment(): { [key: string]: string | string[] } | undefined { - let result: string = ""; - // first resolve variables - result = util.resolveVariables(command); - let file: string | undefined = vscode.window.activeTextEditor?.document.uri.fsPath; - if (file) { - if (result.includes("${file}")) { - result = result.replace("${file}", file); - } - if (result.includes("${fileDirname}")) { - result = result.replace("${fileDirname}", path.dirname(file)); + const editor: vscode.TextEditor | undefined = vscode.window.activeTextEditor; + if (!editor) { + return undefined; + } + const fileDir: vscode.WorkspaceFolder | undefined = vscode.workspace.getWorkspaceFolder(editor.document.uri); + if (!fileDir) { + return undefined; + } + const file: string = editor.document.fileName; + return { "file": file, "fileDirname": fileDir.uri.fsPath, "fileBasenameNoExtension": path.parse(file).name}; + } +} + +export function getRawTasksJson(): Promise { + return new Promise((resolve, reject) => { + const path: string | undefined = getTasksJsonPath(); + if (!path) { + return resolve({}); + } + fs.exists(path, exists => { + if (!exists) { + return resolve({}); } - if (result.includes("${fileBasenameNoExtension}")) { - result = result.replace("${fileBasenameNoExtension}", path.parse(file).name); + let fileContents: string = fs.readFileSync(path).toString(); + fileContents = fileContents.replace(/^\s*\/\/.*$/gm, ""); // Remove start of line // comments. + let rawTasks: any = {}; + try { + rawTasks = JSON.parse(fileContents); + } catch (error) { + return reject(new Error(failedToParseTasksJson)); } - } - return result; + resolve(rawTasks); + }); + }); +} + +export function getTasksJsonPath(): string | undefined { + const editor: vscode.TextEditor | undefined = vscode.window.activeTextEditor; + if (!editor) { + return undefined; + } + const folder: vscode.WorkspaceFolder | undefined = vscode.workspace.getWorkspaceFolder(editor.document.uri); + if (!folder) { + return undefined; } + return path.join(folder.uri.fsPath, ".vscode", "tasks.json"); } diff --git a/Extension/src/common.ts b/Extension/src/common.ts index 8623bb655..7ce3a3a7e 100644 --- a/Extension/src/common.ts +++ b/Extension/src/common.ts @@ -17,7 +17,7 @@ import * as assert from 'assert'; import * as https from 'https'; import * as tmp from 'tmp'; import { ClientRequest, OutgoingHttpHeaders } from 'http'; -import { CppBuildTaskProvider } from './LanguageServer/cppbuildTaskProvider'; +import { getRawTasksJson, getTasksJsonPath, CppBuildTaskProvider } from './LanguageServer/cppbuildTaskProvider'; import { OtherSettings } from './LanguageServer/settings'; import { lookupString } from './nativeStrings'; import * as nls from 'vscode-nls'; @@ -44,8 +44,6 @@ export function setExtensionPath(path: string): void { extensionPath = path; } -export const failedToParseTasksJson: string = localize("failed.to.parse.tasks", "Failed to parse tasks.json, possibly due to comments or trailing commas."); - // Use this package.json to read values export const packageJson: any = vscode.extensions.getExtension("ms-vscode.cpptools")?.packageJSON; @@ -60,28 +58,6 @@ export function getRawPackageJson(): any { return rawPackageJson; } -export function getRawTasksJson(): Promise { - return new Promise((resolve, reject) => { - const path: string | undefined = getTasksJsonPath(); - if (!path) { - return resolve({}); - } - fs.exists(path, exists => { - if (!exists) { - return resolve({}); - } - let fileContents: string = fs.readFileSync(path).toString(); - fileContents = fileContents.replace(/^\s*\/\/.*$/gm, ""); // Remove start of line // comments. - let rawTasks: any = {}; - try { - rawTasks = JSON.parse(fileContents); - } catch (error) { - return reject(new Error(failedToParseTasksJson)); - } - resolve(rawTasks); - }); - }); -} export async function ensureBuildTaskExists(taskName: string): Promise { let rawTasksJson: any = await getRawTasksJson(); @@ -153,18 +129,6 @@ export function getPackageJsonPath(): string { return getExtensionFilePath("package.json"); } -export function getTasksJsonPath(): string | undefined { - const editor: vscode.TextEditor | undefined = vscode.window.activeTextEditor; - if (!editor) { - return undefined; - } - const folder: vscode.WorkspaceFolder | undefined = vscode.workspace.getWorkspaceFolder(editor.document.uri); - if (!folder) { - return undefined; - } - return path.join(folder.uri.fsPath, ".vscode", "tasks.json"); -} - export function getVcpkgPathDescriptorFile(): string { if (process.platform === 'win32') { let pathPrefix: string | undefined = process.env.LOCALAPPDATA; @@ -390,26 +354,6 @@ export function resolveVariables(input: string | undefined, additionalEnvironmen } break; } - case "file": { - newValue = vscode.window.activeTextEditor?.document.uri.toString(); - break; - } - case "fileDirname": { - if (name && vscode.workspace && vscode.workspace.workspaceFolders) { - let folder: vscode.WorkspaceFolder | undefined = vscode.workspace.workspaceFolders.find(folder => folder.name.toLocaleLowerCase() === name.toLocaleLowerCase()); - if (folder) { - newValue = folder.uri.fsPath; - } - } - break; - } - case "fileBasenameNoExtension": { - let fileBaseName: string | undefined = vscode.window.activeTextEditor?.document.uri.toString(); - if (fileBaseName) { - newValue = path.parse(fileBaseName).name; - } - break; - } default: { assert.fail("unknown varType matched"); } } return newValue !== undefined ? newValue : match; From 4b34f16c16a8abd2bc3b7187320ef32bc0d5fed0 Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Tue, 16 Jun 2020 10:32:50 -0700 Subject: [PATCH 07/55] windows version --- Extension/package.json | 10 ++-- .../LanguageServer/cppbuildTaskProvider.ts | 57 ++++++++++++------- 2 files changed, 40 insertions(+), 27 deletions(-) diff --git a/Extension/package.json b/Extension/package.json index 8f0f56042..1a616a069 100644 --- a/Extension/package.json +++ b/Extension/package.json @@ -40,7 +40,7 @@ ], "activationEvents": [ "*" - ], + ], "main": "./dist/main", "contributes": { "taskDefinitions": [ @@ -58,13 +58,13 @@ "type": "string", "description": "The compiler path." }, - "flags": { + "args": { "type": "array", - "description": "Additional build flags." + "description": "Additional build args." }, "options": { - "type": "object", - "description": "Current working directory." + "type": "object", + "description": "Options {\"cwd\": cwd}." } } } diff --git a/Extension/src/LanguageServer/cppbuildTaskProvider.ts b/Extension/src/LanguageServer/cppbuildTaskProvider.ts index 7a910d36b..9e294e99e 100644 --- a/Extension/src/LanguageServer/cppbuildTaskProvider.ts +++ b/Extension/src/LanguageServer/cppbuildTaskProvider.ts @@ -12,7 +12,7 @@ import * as configs from './configurations'; import * as ext from './extension'; import * as fs from 'fs'; import * as nls from 'vscode-nls'; -import { exec } from "child_process"; +import * as cp from "child_process"; const localize: nls.LocalizeFunc = nls.loadMessageBundle(); export const failedToParseTasksJson: string = localize("failed.to.parse.tasks", "Failed to parse tasks.json, possibly due to comments or trailing commas."); @@ -22,7 +22,7 @@ export interface CppBuildTaskDefinition extends vscode.TaskDefinition { label: string; command: string; args: string[]; - options: undefined | Record; + options: cp.ProcessEnvOptions | undefined; } export class CppBuildTaskProvider implements vscode.TaskProvider { @@ -33,13 +33,16 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { constructor() {} public async provideTasks(): Promise { + if (this.tasks !== undefined) { + return this.tasks; + } return this.getTasks(false, false); } + // Resolves a task that has no [`execution`](#Task.execution) set. public resolveTask(_task: vscode.Task): vscode.Task | undefined { - // return this.getTask(compilerPath, compilerArgs); - const command: string = _task.definition.command; - if (command) { + const execution: vscode.ProcessExecution | vscode.ShellExecution | vscode.CustomExecution | undefined = _task.execution; + if (execution === undefined) { const definition: CppBuildTaskDefinition = _task.definition; return this.getTask(definition.command, false, false, definition.args ? definition.args : [], definition); } @@ -48,6 +51,9 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { // Generate tasks to build the current file based on the user's detected compilers, the user's compilerPath setting, and the current file's extension. public async getTasks(returnCompilerPath: boolean, appendSourceToName: boolean): Promise { + if (this.tasks !== undefined) { + return this.tasks; + } this.tasks = []; const editor: vscode.TextEditor | undefined = vscode.window.activeTextEditor; if (!editor) { @@ -148,26 +154,26 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { const taskName: string = (appendSourceToName ? CppBuildTaskProvider.CppBuildSourceStr + ": " : "") + compilerPathBase + " build active file"; const isCl: boolean = compilerPathBase === "cl.exe"; const isWindows: boolean = os.platform() === 'win32'; - const cwd: string = isCl ? "" : path.dirname(compilerPath); + const cwd: string = isCl ? "${workspaceFolder}" : path.dirname(compilerPath); let args: string[] = isCl ? ['/Zi', '/EHsc', '/Fe:', filePath + '.exe', '${file}'] : ['-g', '${file}', '-o', filePath + (isWindows ? '.exe' : '')]; - if (compilerArgs && compilerArgs.length > 0) { + if (definition === undefined && compilerArgs && compilerArgs.length > 0) { args = args.concat(compilerArgs); } + const options: cp.ProcessEnvOptions | undefined = {"cwd": cwd}; // Double-quote the command if it is not already double-quoted. let resolvedcompilerPath: string = isCl ? compilerPathBase : compilerPath; - if (resolvedcompilerPath && !resolvedcompilerPath.startsWith("\"")) { + if (resolvedcompilerPath && !resolvedcompilerPath.startsWith("\"") && resolvedcompilerPath.includes(" ")) { resolvedcompilerPath = "\"" + resolvedcompilerPath + "\""; } - const command: string = resolvedcompilerPath + " " + args.join(" "); if (definition === undefined) { definition = { type: CppBuildTaskProvider.CppBuildScriptType, label: taskName, - command: command, + command: resolvedcompilerPath, args: args, - options: isCl ? undefined : {"cwd": cwd} + options: options }; } @@ -189,7 +195,7 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { let task: vscode.Task = new vscode.Task(definition, target, taskName, CppBuildTaskProvider.CppBuildSourceStr, new vscode.CustomExecution(async (): Promise => // When the task is executed, this callback will run. Here, we setup for running the task. - new CustomBuildTaskTerminal(command) + new CustomBuildTaskTerminal(resolvedcompilerPath, args, options, target.name) ), isCl ? '$msCompile' : '$gcc'); /* const normalcommand: vscode.ShellExecution = new vscode.ShellExecution(compilerPath, [...args], { cwd: cwd }); @@ -211,15 +217,18 @@ class CustomBuildTaskTerminal implements vscode.Pseudoterminal { private fileWatcher: vscode.FileSystemWatcher | undefined; - private command: string; - constructor(command: string) { - this.command = command; + constructor(private command: string, private args: string[], private options: cp.ProcessEnvOptions | undefined, private workspaceRoot: string) { } open(initialDimensions: vscode.TerminalDimensions | undefined): void { telemetry.logLanguageServerEvent("cppBuildTaskStarted"); + const pattern: string = path.join(this.workspaceRoot, 'cppBuild'); + this.fileWatcher = vscode.workspace.createFileSystemWatcher(pattern); + this.fileWatcher.onDidChange(() => this.doBuild()); + this.fileWatcher.onDidCreate(() => this.doBuild()); + this.fileWatcher.onDidDelete(() => this.doBuild()); // At this point we can start using the terminal. this.writeEmitter.fire("Starting build...\r\n"); this.doBuild(); @@ -233,22 +242,26 @@ class CustomBuildTaskTerminal implements vscode.Pseudoterminal { } private async doBuild(): Promise { - return new Promise((resolve) => { + return new Promise((resolve, reject) => { // Do build. - const activeCommand: string = util.resolveVariables(this.command, this.AdditionalEnvironment); - exec(activeCommand, (_error, stdout, stderr) => { - this.writeEmitter.fire(stdout); - this.writeEmitter.fire(stderr); + const activeCommand: string = util.resolveVariables(this.command + " " + this.args.join(" "), this.AdditionalEnvironment); + cp.exec(activeCommand, this.options, (_error, stdout, stderr) => { if (_error) { - telemetry.logLanguageServerEvent("cppBuildTaskError"); + telemetry.logLanguageServerEvent("cppBuildTaskError", { "error": stderr.toString() }); + this.writeEmitter.fire(stderr.toString()); this.writeEmitter.fire("Build finished with error.\r\n"); + reject(); } else { + this.writeEmitter.fire(stdout.toString()); this.writeEmitter.fire("Build finished successfully.\r\n"); + resolve(); } }); + }).finally (() => { this.writeEmitter.fire("\r\n"); + this.closeEmitter.fire(); // Set timeout to give enough time to the writeEmitter to print all messages. - setTimeout(() => {this.closeEmitter.fire(); }, 3000); + // setTimeout(() => {this.closeEmitter.fire(); }, 3000); }); } From d8403f1c2afa963439b1387a8a970e02b606d7b9 Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Tue, 16 Jun 2020 13:53:58 -0700 Subject: [PATCH 08/55] fix cwd path --- .../src/LanguageServer/cppbuildTaskProvider.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Extension/src/LanguageServer/cppbuildTaskProvider.ts b/Extension/src/LanguageServer/cppbuildTaskProvider.ts index 9e294e99e..3f8f63cc6 100644 --- a/Extension/src/LanguageServer/cppbuildTaskProvider.ts +++ b/Extension/src/LanguageServer/cppbuildTaskProvider.ts @@ -245,23 +245,23 @@ class CustomBuildTaskTerminal implements vscode.Pseudoterminal { return new Promise((resolve, reject) => { // Do build. const activeCommand: string = util.resolveVariables(this.command + " " + this.args.join(" "), this.AdditionalEnvironment); + if (this.options?.cwd) { + this.options.cwd = util.resolveVariables(this.options.cwd, this.AdditionalEnvironment); + } cp.exec(activeCommand, this.options, (_error, stdout, stderr) => { if (_error) { - telemetry.logLanguageServerEvent("cppBuildTaskError", { "error": stderr.toString() }); - this.writeEmitter.fire(stderr.toString()); - this.writeEmitter.fire("Build finished with error.\r\n"); + telemetry.logLanguageServerEvent("cppBuildTaskError", { "error": _error.message }); + this.writeEmitter.fire("Build finished with error:\r\n"); + this.writeEmitter.fire("\t" + _error.message + "\r\n"); reject(); } else { this.writeEmitter.fire(stdout.toString()); - this.writeEmitter.fire("Build finished successfully.\r\n"); + this.writeEmitter.fire("\r\nBuild finished successfully.\r\n"); resolve(); } }); }).finally (() => { - this.writeEmitter.fire("\r\n"); this.closeEmitter.fire(); - // Set timeout to give enough time to the writeEmitter to print all messages. - // setTimeout(() => {this.closeEmitter.fire(); }, 3000); }); } From 8b93a059b33c90d4d19e20cb1e8e644fa92b7ddc Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Wed, 17 Jun 2020 16:26:00 -0700 Subject: [PATCH 09/55] fix cwd --- Extension/src/LanguageServer/cppbuildTaskProvider.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Extension/src/LanguageServer/cppbuildTaskProvider.ts b/Extension/src/LanguageServer/cppbuildTaskProvider.ts index 3f8f63cc6..f3f74f50e 100644 --- a/Extension/src/LanguageServer/cppbuildTaskProvider.ts +++ b/Extension/src/LanguageServer/cppbuildTaskProvider.ts @@ -276,7 +276,11 @@ class CustomBuildTaskTerminal implements vscode.Pseudoterminal { return undefined; } const file: string = editor.document.fileName; - return { "file": file, "fileDirname": fileDir.uri.fsPath, "fileBasenameNoExtension": path.parse(file).name}; + return { + "file": file, + "fileDirname": fileDir.uri.fsPath, + "fileBasenameNoExtension": path.parse(file).name, + "workspaceFolder": fileDir.uri.fsPath}; } } From 5e2da4ec839b6873e9fe70140fe03415bbf607f0 Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Mon, 22 Jun 2020 10:42:28 -0700 Subject: [PATCH 10/55] change header and source file set --- Extension/src/LanguageServer/cppbuildTaskProvider.ts | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/Extension/src/LanguageServer/cppbuildTaskProvider.ts b/Extension/src/LanguageServer/cppbuildTaskProvider.ts index f3f74f50e..110cb8f9d 100644 --- a/Extension/src/LanguageServer/cppbuildTaskProvider.ts +++ b/Extension/src/LanguageServer/cppbuildTaskProvider.ts @@ -67,7 +67,7 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { // Don't offer tasks for header files. const fileExtLower: string = fileExt.toLowerCase(); - const isHeader: boolean = !fileExt || [".hpp", ".hh", ".hxx", ".h", ".inl", ""].some(ext => fileExtLower === ext); + const isHeader: boolean = !fileExt || ["*.hpp", "*.hh", "*.hxx", "*.h++", "*.hp", "*.h", "*.ii", "*.inl", "*.idl", ""].some(ext => fileExtLower === ext); if (isHeader) { return []; } @@ -79,7 +79,7 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { fileIsCpp = true; fileIsC = true; } else { - fileIsCpp = [".cpp", ".cc", ".cxx", ".mm", ".ino"].some(ext => fileExtLower === ext); + fileIsCpp = ["*.cpp", "*.cc", "*.cxx", "*.c++", "*.cp", "*.ino", "*.ipp", "*.tcc"].some(ext => fileExtLower === ext); fileIsC = fileExtLower === ".c"; } if (!(fileIsCpp || fileIsC)) { @@ -209,11 +209,9 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { class CustomBuildTaskTerminal implements vscode.Pseudoterminal { private writeEmitter = new vscode.EventEmitter(); - // eslint-disable-next-line no-invalid-this - onDidWrite: vscode.Event = this.writeEmitter.event; private closeEmitter = new vscode.EventEmitter(); - // eslint-disable-next-line no-invalid-this - onDidClose?: vscode.Event = this.closeEmitter.event; + public get onDidWrite(): vscode.Event { return this.writeEmitter.event; } + public get onDidClose(): vscode.Event { return this.closeEmitter.event; } private fileWatcher: vscode.FileSystemWatcher | undefined; From 9f29e3d531d93d535fd00bc1639831a12e0bc4a9 Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Mon, 22 Jun 2020 15:35:09 -0700 Subject: [PATCH 11/55] minor changes --- .../src/LanguageServer/cppbuildTaskProvider.ts | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/Extension/src/LanguageServer/cppbuildTaskProvider.ts b/Extension/src/LanguageServer/cppbuildTaskProvider.ts index 110cb8f9d..575e29d52 100644 --- a/Extension/src/LanguageServer/cppbuildTaskProvider.ts +++ b/Extension/src/LanguageServer/cppbuildTaskProvider.ts @@ -33,7 +33,7 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { constructor() {} public async provideTasks(): Promise { - if (this.tasks !== undefined) { + if (this.tasks) { return this.tasks; } return this.getTasks(false, false); @@ -42,7 +42,7 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { // Resolves a task that has no [`execution`](#Task.execution) set. public resolveTask(_task: vscode.Task): vscode.Task | undefined { const execution: vscode.ProcessExecution | vscode.ShellExecution | vscode.CustomExecution | undefined = _task.execution; - if (execution === undefined) { + if (!execution) { const definition: CppBuildTaskDefinition = _task.definition; return this.getTask(definition.command, false, false, definition.args ? definition.args : [], definition); } @@ -54,7 +54,6 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { if (this.tasks !== undefined) { return this.tasks; } - this.tasks = []; const editor: vscode.TextEditor | undefined = vscode.window.activeTextEditor; if (!editor) { return []; @@ -67,7 +66,7 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { // Don't offer tasks for header files. const fileExtLower: string = fileExt.toLowerCase(); - const isHeader: boolean = !fileExt || ["*.hpp", "*.hh", "*.hxx", "*.h++", "*.hp", "*.h", "*.ii", "*.inl", "*.idl", ""].some(ext => fileExtLower === ext); + const isHeader: boolean = !fileExt || [".hpp", ".hh", ".hxx", ".h++", ".hp", ".h", ".ii", ".inl", ".idl", ""].some(ext => fileExtLower === ext); if (isHeader) { return []; } @@ -79,7 +78,7 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { fileIsCpp = true; fileIsC = true; } else { - fileIsCpp = ["*.cpp", "*.cc", "*.cxx", "*.c++", "*.cp", "*.ino", "*.ipp", "*.tcc"].some(ext => fileExtLower === ext); + fileIsCpp = [".cpp", ".cc", ".cxx", ".c++", ".cp", ".ino", ".ipp", ".tcc"].some(ext => fileExtLower === ext); fileIsC = fileExtLower === ".c"; } if (!(fileIsCpp || fileIsC)) { @@ -133,12 +132,11 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { } // Create a build task per compiler path - + this.tasks = []; // Tasks for known compiler paths if (knownCompilerPaths) { this.tasks = knownCompilerPaths.map(compilerPath => this.getTask(compilerPath, returnCompilerPath, appendSourceToName, undefined)); } - // Task for user compiler path setting if (userCompilerPath) { this.tasks.push(this.getTask(userCompilerPath, returnCompilerPath, appendSourceToName, userCompilerPathAndArgs?.additionalArgs)); @@ -148,7 +146,6 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { } private getTask: (compilerPath: string, returnCompilerPath: boolean, appendSourceToName: boolean, compilerArgs?: string [], definition?: CppBuildTaskDefinition) => vscode.Task = (compilerPath: string, returnCompilerPath: boolean, appendSourceToName: boolean, compilerArgs?: string [], definition?: CppBuildTaskDefinition) => { - const filePath: string = path.join('${fileDirname}', '${fileBasenameNoExtension}'); const compilerPathBase: string = path.basename(compilerPath); const taskName: string = (appendSourceToName ? CppBuildTaskProvider.CppBuildSourceStr + ": " : "") + compilerPathBase + " build active file"; @@ -156,7 +153,7 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { const isWindows: boolean = os.platform() === 'win32'; const cwd: string = isCl ? "${workspaceFolder}" : path.dirname(compilerPath); let args: string[] = isCl ? ['/Zi', '/EHsc', '/Fe:', filePath + '.exe', '${file}'] : ['-g', '${file}', '-o', filePath + (isWindows ? '.exe' : '')]; - if (definition === undefined && compilerArgs && compilerArgs.length > 0) { + if (!definition && compilerArgs && compilerArgs.length > 0) { args = args.concat(compilerArgs); } const options: cp.ProcessEnvOptions | undefined = {"cwd": cwd}; @@ -167,7 +164,7 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { resolvedcompilerPath = "\"" + resolvedcompilerPath + "\""; } - if (definition === undefined) { + if (!definition) { definition = { type: CppBuildTaskProvider.CppBuildScriptType, label: taskName, From 95284c6bbb2c0c8196a7058d10bcc6197de721ea Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Mon, 22 Jun 2020 16:29:56 -0700 Subject: [PATCH 12/55] make new instance --- Extension/src/Debugger/configurationProvider.ts | 5 +++-- Extension/src/LanguageServer/extension.ts | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Extension/src/Debugger/configurationProvider.ts b/Extension/src/Debugger/configurationProvider.ts index 2d8943896..cf3844364 100644 --- a/Extension/src/Debugger/configurationProvider.ts +++ b/Extension/src/Debugger/configurationProvider.ts @@ -7,11 +7,12 @@ import * as debugUtils from './utils'; import * as os from 'os'; import * as path from 'path'; import * as vscode from 'vscode'; -import { CppBuildTaskProvider, CppBuildTaskDefinition} from '../LanguageServer/cppbuildTaskProvider'; +import { CppBuildTaskDefinition} from '../LanguageServer/cppbuildTaskProvider'; import * as util from '../common'; import * as fs from 'fs'; import * as Telemetry from '../telemetry'; import { buildAndDebugActiveFileStr } from './extension'; +import { cppBuildTaskProvider} from '../LanguageServer/extension'; import * as logger from '../logger'; import * as nls from 'vscode-nls'; @@ -105,7 +106,7 @@ class CppConfigurationProvider implements vscode.DebugConfigurationProvider { * Returns a list of initial debug configurations based on contextual information, e.g. package.json or folder. */ async provideDebugConfigurations(folder?: vscode.WorkspaceFolder, token?: vscode.CancellationToken): Promise { - let buildTasks: vscode.Task[] = await new CppBuildTaskProvider().getTasks(true, true); + let buildTasks: vscode.Task[] = await cppBuildTaskProvider.getTasks(true, true); if (buildTasks.length === 0) { return Promise.resolve(this.provider.getInitialConfigurations(this.type)); } diff --git a/Extension/src/LanguageServer/extension.ts b/Extension/src/LanguageServer/extension.ts index 751da7fd7..d279690d2 100644 --- a/Extension/src/LanguageServer/extension.ts +++ b/Extension/src/LanguageServer/extension.ts @@ -32,6 +32,7 @@ import { CppBuildTaskProvider } from './cppbuildTaskProvider'; nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })(); const localize: nls.LocalizeFunc = nls.loadMessageBundle(); +export let cppBuildTaskProvider: CppBuildTaskProvider = new CppBuildTaskProvider(); let prevCrashFile: string; let clients: ClientCollection; @@ -170,7 +171,7 @@ export function activate(activationEventOccurred: boolean): void { return; } - taskProvider = vscode.tasks.registerTaskProvider(CppBuildTaskProvider.CppBuildScriptType, new CppBuildTaskProvider()); + taskProvider = vscode.tasks.registerTaskProvider(CppBuildTaskProvider.CppBuildScriptType, cppBuildTaskProvider); vscode.tasks.onDidStartTask(event => { if (event.execution.task.source === CppBuildTaskProvider.CppBuildSourceStr) { From ecc01a1648b16f4c65c3289e87e1c118fd2b50a3 Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Mon, 22 Jun 2020 16:44:14 -0700 Subject: [PATCH 13/55] create new instance --- .../src/Debugger/configurationProvider.ts | 2 +- Extension/src/Debugger/extension.ts | 3 +- .../LanguageServer/cppbuildTaskProvider.ts | 43 +++++++++++++++++ Extension/src/common.ts | 46 +------------------ 4 files changed, 47 insertions(+), 47 deletions(-) diff --git a/Extension/src/Debugger/configurationProvider.ts b/Extension/src/Debugger/configurationProvider.ts index cf3844364..6165904ba 100644 --- a/Extension/src/Debugger/configurationProvider.ts +++ b/Extension/src/Debugger/configurationProvider.ts @@ -78,7 +78,7 @@ export class QuickPickConfigurationProvider implements vscode.DebugConfiguration } if (selection.label.indexOf(buildAndDebugActiveFileStr()) !== -1 && selection.configuration.preLaunchTask) { try { - await util.ensureBuildTaskExists(selection.configuration.preLaunchTask); + await cppBuildTaskProvider.ensureBuildTaskExists(selection.configuration.preLaunchTask); await vscode.debug.startDebugging(folder, selection.configuration); Telemetry.logDebuggerEvent("buildAndDebug", { "success": "true" }); } catch (e) { diff --git a/Extension/src/Debugger/extension.ts b/Extension/src/Debugger/extension.ts index 41a2c6b87..baca62d98 100644 --- a/Extension/src/Debugger/extension.ts +++ b/Extension/src/Debugger/extension.ts @@ -13,6 +13,7 @@ import { failedToParseTasksJson } from '../LanguageServer/cppbuildTaskProvider'; import * as util from '../common'; import * as Telemetry from '../telemetry'; import * as nls from 'vscode-nls'; +import { cppBuildTaskProvider } from '../LanguageServer/extension'; nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })(); const localize: nls.LocalizeFunc = nls.loadMessageBundle(); @@ -89,7 +90,7 @@ export function initialize(context: vscode.ExtensionContext): void { if (selection.configuration.preLaunchTask) { if (folder) { try { - await util.ensureBuildTaskExists(selection.configuration.preLaunchTask); + await cppBuildTaskProvider.ensureBuildTaskExists(selection.configuration.preLaunchTask); Telemetry.logDebuggerEvent("buildAndDebug", { "success": "false" }); } catch (e) { if (e && e.message === failedToParseTasksJson) { diff --git a/Extension/src/LanguageServer/cppbuildTaskProvider.ts b/Extension/src/LanguageServer/cppbuildTaskProvider.ts index 575e29d52..632a8686b 100644 --- a/Extension/src/LanguageServer/cppbuildTaskProvider.ts +++ b/Extension/src/LanguageServer/cppbuildTaskProvider.ts @@ -13,6 +13,7 @@ import * as ext from './extension'; import * as fs from 'fs'; import * as nls from 'vscode-nls'; import * as cp from "child_process"; +import { OtherSettings } from './settings'; const localize: nls.LocalizeFunc = nls.loadMessageBundle(); export const failedToParseTasksJson: string = localize("failed.to.parse.tasks", "Failed to parse tasks.json, possibly due to comments or trailing commas."); @@ -202,6 +203,48 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { return task; }; + + async ensureBuildTaskExists(taskName: string): Promise { + let rawTasksJson: any = await getRawTasksJson(); + + // Ensure that the task exists in the user's task.json. Task will not be found otherwise. + if (!rawTasksJson.tasks) { + rawTasksJson.tasks = new Array(); + } + // Find or create the task which should be created based on the selected "debug configuration". + let selectedTask: vscode.Task | undefined = rawTasksJson.tasks.find((task: any) => task.label && task.label === task); + if (selectedTask) { + return; + } + + const buildTasks: vscode.Task[] = await this.getTasks(false, true); + selectedTask = buildTasks.find(task => task.name === taskName); + console.assert(selectedTask); + if (!selectedTask) { + throw new Error("Failed to get selectedTask in ensureBuildTaskExists()"); + } + + rawTasksJson.version = "2.0.0"; + + let selectedTask2: vscode.Task = selectedTask; + if (!rawTasksJson.tasks.find((task: any) => task.label === selectedTask2.definition.label)) { + let task: any = { + ...selectedTask2.definition, + problemMatcher: selectedTask2.problemMatchers, + group: { kind: "build", "isDefault": true } + }; + rawTasksJson.tasks.push(task); + } + + // TODO: It's dangerous to overwrite this file. We could be wiping out comments. + let settings: OtherSettings = new OtherSettings(); + let tasksJsonPath: string | undefined = getTasksJsonPath(); + if (!tasksJsonPath) { + throw new Error("Failed to get tasksJsonPath in ensureBuildTaskExists()"); + } + + await util.writeFileText(tasksJsonPath, JSON.stringify(rawTasksJson, null, settings.editorTabSize)); + } } class CustomBuildTaskTerminal implements vscode.Pseudoterminal { diff --git a/Extension/src/common.ts b/Extension/src/common.ts index 7ce3a3a7e..8150c10ff 100644 --- a/Extension/src/common.ts +++ b/Extension/src/common.ts @@ -17,8 +17,7 @@ import * as assert from 'assert'; import * as https from 'https'; import * as tmp from 'tmp'; import { ClientRequest, OutgoingHttpHeaders } from 'http'; -import { getRawTasksJson, getTasksJsonPath, CppBuildTaskProvider } from './LanguageServer/cppbuildTaskProvider'; -import { OtherSettings } from './LanguageServer/settings'; + import { lookupString } from './nativeStrings'; import * as nls from 'vscode-nls'; import { Readable } from 'stream'; @@ -58,49 +57,6 @@ export function getRawPackageJson(): any { return rawPackageJson; } - -export async function ensureBuildTaskExists(taskName: string): Promise { - let rawTasksJson: any = await getRawTasksJson(); - - // Ensure that the task exists in the user's task.json. Task will not be found otherwise. - if (!rawTasksJson.tasks) { - rawTasksJson.tasks = new Array(); - } - // Find or create the task which should be created based on the selected "debug configuration". - let selectedTask: vscode.Task | undefined = rawTasksJson.tasks.find((task: any) => task.label && task.label === task); - if (selectedTask) { - return; - } - - const buildTasks: vscode.Task[] = await new CppBuildTaskProvider().getTasks(false, true); - selectedTask = buildTasks.find(task => task.name === taskName); - console.assert(selectedTask); - if (!selectedTask) { - throw new Error("Failed to get selectedTask in ensureBuildTaskExists()"); - } - - rawTasksJson.version = "2.0.0"; - - let selectedTask2: vscode.Task = selectedTask; - if (!rawTasksJson.tasks.find((task: any) => task.label === selectedTask2.definition.label)) { - let task: any = { - ...selectedTask2.definition, - problemMatcher: selectedTask2.problemMatchers, - group: { kind: "build", "isDefault": true } - }; - rawTasksJson.tasks.push(task); - } - - // TODO: It's dangerous to overwrite this file. We could be wiping out comments. - let settings: OtherSettings = new OtherSettings(); - let tasksJsonPath: string | undefined = getTasksJsonPath(); - if (!tasksJsonPath) { - throw new Error("Failed to get tasksJsonPath in ensureBuildTaskExists()"); - } - - await writeFileText(tasksJsonPath, JSON.stringify(rawTasksJson, null, settings.editorTabSize)); -} - export function fileIsCOrCppSource(file: string): boolean { const fileExtLower: string = path.extname(file).toLowerCase(); return [".C", ".c", ".cpp", ".cc", ".cxx", ".mm", ".ino", ".inl"].some(ext => fileExtLower === ext); From f73ad8f2c69e2359ba0f726968dd51d60aa6920a Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Tue, 23 Jun 2020 00:34:22 -0700 Subject: [PATCH 14/55] remove compilerPath input --- Extension/package.json | 2 +- .../src/Debugger/configurationProvider.ts | 7 +++--- .../LanguageServer/cppbuildTaskProvider.ts | 24 +++++++------------ 3 files changed, 13 insertions(+), 20 deletions(-) diff --git a/Extension/package.json b/Extension/package.json index 1a616a069..49507d59f 100644 --- a/Extension/package.json +++ b/Extension/package.json @@ -65,7 +65,7 @@ "options": { "type": "object", "description": "Options {\"cwd\": cwd}." - } + } } } ], diff --git a/Extension/src/Debugger/configurationProvider.ts b/Extension/src/Debugger/configurationProvider.ts index 6165904ba..4b63ef658 100644 --- a/Extension/src/Debugger/configurationProvider.ts +++ b/Extension/src/Debugger/configurationProvider.ts @@ -106,7 +106,7 @@ class CppConfigurationProvider implements vscode.DebugConfigurationProvider { * Returns a list of initial debug configurations based on contextual information, e.g. package.json or folder. */ async provideDebugConfigurations(folder?: vscode.WorkspaceFolder, token?: vscode.CancellationToken): Promise { - let buildTasks: vscode.Task[] = await cppBuildTaskProvider.getTasks(true, true); + let buildTasks: vscode.Task[] = await cppBuildTaskProvider.getTasks(true); if (buildTasks.length === 0) { return Promise.resolve(this.provider.getInitialConfigurations(this.type)); } @@ -135,7 +135,8 @@ class CppConfigurationProvider implements vscode.DebugConfigurationProvider { // Generating a task is async, therefore we must *await* *all* map(task => config) Promises to resolve. let configs: vscode.DebugConfiguration[] = await Promise.all(buildTasks.map>(async task => { const definition: CppBuildTaskDefinition = task.definition as CppBuildTaskDefinition; - const compilerName: string = path.basename(definition.compilerPath); + const compilerPath: string = definition.command; + const compilerName: string = path.basename(compilerPath); let newConfig: vscode.DebugConfiguration = {...defaultConfig}; // Copy enumerables and properties @@ -167,7 +168,7 @@ class CppConfigurationProvider implements vscode.DebugConfigurationProvider { debuggerName += ".exe"; } - const compilerDirname: string = path.dirname(definition.compilerPath); + const compilerDirname: string = path.dirname(compilerPath); const debuggerPath: string = path.join(compilerDirname, debuggerName); fs.stat(debuggerPath, (err, stats: fs.Stats) => { if (!err && stats && stats.isFile) { diff --git a/Extension/src/LanguageServer/cppbuildTaskProvider.ts b/Extension/src/LanguageServer/cppbuildTaskProvider.ts index 632a8686b..215acad5b 100644 --- a/Extension/src/LanguageServer/cppbuildTaskProvider.ts +++ b/Extension/src/LanguageServer/cppbuildTaskProvider.ts @@ -37,7 +37,7 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { if (this.tasks) { return this.tasks; } - return this.getTasks(false, false); + return this.getTasks(false); } // Resolves a task that has no [`execution`](#Task.execution) set. @@ -45,13 +45,13 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { const execution: vscode.ProcessExecution | vscode.ShellExecution | vscode.CustomExecution | undefined = _task.execution; if (!execution) { const definition: CppBuildTaskDefinition = _task.definition; - return this.getTask(definition.command, false, false, definition.args ? definition.args : [], definition); + return this.getTask(definition.command, false, definition.args ? definition.args : [], definition); } return undefined; } // Generate tasks to build the current file based on the user's detected compilers, the user's compilerPath setting, and the current file's extension. - public async getTasks(returnCompilerPath: boolean, appendSourceToName: boolean): Promise { + public async getTasks(appendSourceToName: boolean): Promise { if (this.tasks !== undefined) { return this.tasks; } @@ -136,17 +136,17 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { this.tasks = []; // Tasks for known compiler paths if (knownCompilerPaths) { - this.tasks = knownCompilerPaths.map(compilerPath => this.getTask(compilerPath, returnCompilerPath, appendSourceToName, undefined)); + this.tasks = knownCompilerPaths.map(compilerPath => this.getTask(compilerPath, appendSourceToName, undefined)); } // Task for user compiler path setting if (userCompilerPath) { - this.tasks.push(this.getTask(userCompilerPath, returnCompilerPath, appendSourceToName, userCompilerPathAndArgs?.additionalArgs)); + this.tasks.push(this.getTask(userCompilerPath, appendSourceToName, userCompilerPathAndArgs?.additionalArgs)); } return this.tasks; } - private getTask: (compilerPath: string, returnCompilerPath: boolean, appendSourceToName: boolean, compilerArgs?: string [], definition?: CppBuildTaskDefinition) => vscode.Task = (compilerPath: string, returnCompilerPath: boolean, appendSourceToName: boolean, compilerArgs?: string [], definition?: CppBuildTaskDefinition) => { + private getTask: (compilerPath: string, appendSourceToName: boolean, compilerArgs?: string [], definition?: CppBuildTaskDefinition) => vscode.Task = (compilerPath: string, appendSourceToName: boolean, compilerArgs?: string [], definition?: CppBuildTaskDefinition) => { const filePath: string = path.join('${fileDirname}', '${fileBasenameNoExtension}'); const compilerPathBase: string = path.basename(compilerPath); const taskName: string = (appendSourceToName ? CppBuildTaskProvider.CppBuildSourceStr + ": " : "") + compilerPathBase + " build active file"; @@ -175,11 +175,6 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { }; } - if (returnCompilerPath) { - definition = definition as CppBuildTaskDefinition; - definition.compilerPath = isCl ? compilerPathBase : compilerPath; - } - let activeClient: Client = ext.getActiveClient(); let uri: vscode.Uri | undefined = activeClient.RootUri; if (!uri) { @@ -196,9 +191,6 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { new CustomBuildTaskTerminal(resolvedcompilerPath, args, options, target.name) ), isCl ? '$msCompile' : '$gcc'); - /* const normalcommand: vscode.ShellExecution = new vscode.ShellExecution(compilerPath, [...args], { cwd: cwd }); - let task: vscode.Task = new vscode.Task(definition, target, taskName, CppBuildTaskProvider.CppBuildSourceStr, - normalcommand, isCl ? '$msCompile' : '$gcc');*/ task.group = vscode.TaskGroup.Build; return task; @@ -212,12 +204,12 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { rawTasksJson.tasks = new Array(); } // Find or create the task which should be created based on the selected "debug configuration". - let selectedTask: vscode.Task | undefined = rawTasksJson.tasks.find((task: any) => task.label && task.label === task); + let selectedTask: vscode.Task | undefined = rawTasksJson.tasks.find((task: any) => task.label && task.label === taskName); if (selectedTask) { return; } - const buildTasks: vscode.Task[] = await this.getTasks(false, true); + const buildTasks: vscode.Task[] = await this.getTasks(true); selectedTask = buildTasks.find(task => task.name === taskName); console.assert(selectedTask); if (!selectedTask) { From 142105cf70592d29c3720eda43aae95c204c52e2 Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Tue, 23 Jun 2020 01:30:16 -0700 Subject: [PATCH 15/55] review changes --- Extension/package.json | 42 +++++++++---------- Extension/package.nls.json | 2 +- .../src/Debugger/configurationProvider.ts | 2 +- Extension/src/Debugger/extension.ts | 2 +- .../LanguageServer/cppbuildTaskProvider.ts | 14 +++---- Extension/src/LanguageServer/extension.ts | 2 +- 6 files changed, 32 insertions(+), 32 deletions(-) diff --git a/Extension/package.json b/Extension/package.json index 49507d59f..33defc502 100644 --- a/Extension/package.json +++ b/Extension/package.json @@ -40,35 +40,35 @@ ], "activationEvents": [ "*" - ], + ], "main": "./dist/main", "contributes": { "taskDefinitions": [ - { - "type": "cppbuild", - "required": [ - "command" - ], - "properties": { + { + "type": "cppbuild", + "required": [ + "command" + ], + "properties": { "label": { - "type": "string", - "description": "Task's name." - }, - "command": { - "type": "string", - "description": "The compiler path." - }, - "args": { - "type": "array", - "description": "Additional build args." + "type": "string", + "description": "Task's name." + }, + "command": { + "type": "string", + "description": "The compiler path." + }, + "args": { + "type": "array", + "description": "Additional build args." }, "options": { "type": "object", - "description": "Options {\"cwd\": cwd}." + "description": "Options" } - } - } - ], + } + } + ], "views": { "references-view": [ { diff --git a/Extension/package.nls.json b/Extension/package.nls.json index 897d9ce21..d7b17c9a7 100644 --- a/Extension/package.nls.json +++ b/Extension/package.nls.json @@ -18,7 +18,7 @@ "c_cpp.command.vcpkgClipboardInstallSuggested.title": "Copy vcpkg install command to clipboard", "c_cpp.command.vcpkgOnlineHelpSuggested.title": "Visit the vcpkg help page", "c_cpp.configuration.clang_format_path.description": "The full path of the clang-format executable. If not specified, and clang-format is available in the environment path, that is used. If not found in the environment path, a copy of clang-format bundled with the extension will be used.", - "c_cpp.configuration.clang_format_style.description": "Coding style, currently supports: Visual Studio, LLVM, Google, Chromium, Mozilla, WebKit. Use \"file\" to load the style from a .clang-format file in the current or parent directory. Use {key: value, ...} to set specific parameters. For example, the \"Visual Studio\" style is similar to: { BasedOnStyle: LLVM, UseTab: Never, IndentWidth: 4, TabWidth: 4, BreakBeforeBraces: Allman, AllowShortIfStatementsOnASingleLine: false, IndentCaseLabels: false, ColumnLimit: 0, AccessModifierOffset: -4, NamespaceIndentation: All, Standard: Cpp03 }", + "c_cpp.configuration.clang_format_style.description": "Coding style, currently supports: Visual Studio, LLVM, Google, Chromium, Mozilla, WebKit. Use \"file\" to load the style from a .clang-format file in the current or parent directory. Use {key: value, ...} to set specific parameters. For example, the \"Visual Studio\" style is similar to: { BasedOnStyle: LLVM, UseTab: Never, IndentWidth: 4, TabWidth: 4, BreakBeforeBraces: Allman, AllowShortIfStatementsOnASingleLine: false, IndentCaseLabels: false, ColumnLimit: 0, AccessModifierOffset: -4, NamespaceIndentation: All }", "c_cpp.configuration.clang_format_fallbackStyle.description": "Name of the predefined style used as a fallback in case clang-format is invoked with style \"file\" but the .clang-format file is not found. Possible values are Visual Studio, LLVM, Google, Chromium, Mozilla, WebKit, none, or use {key: value, ...} to set specific parameters. For example, the \"Visual Studio\" style is similar to: { BasedOnStyle: LLVM, UseTab: Never, IndentWidth: 4, TabWidth: 4, BreakBeforeBraces: Allman, AllowShortIfStatementsOnASingleLine: false, IndentCaseLabels: false, ColumnLimit: 0, AccessModifierOffset: -4 }", "c_cpp.configuration.clang_format_sortIncludes.description": "If set, overrides the include sorting behavior determined by the SortIncludes parameter.", "c_cpp.configuration.intelliSenseEngine.description": "Controls the IntelliSense provider. \"Tag Parser\" provides \"fuzzy\" results that are not context-aware. \"Default\" provides context-aware results. \"Disabled\" turns off C/C++ language service features.", diff --git a/Extension/src/Debugger/configurationProvider.ts b/Extension/src/Debugger/configurationProvider.ts index 4b63ef658..b3705e3a1 100644 --- a/Extension/src/Debugger/configurationProvider.ts +++ b/Extension/src/Debugger/configurationProvider.ts @@ -7,7 +7,7 @@ import * as debugUtils from './utils'; import * as os from 'os'; import * as path from 'path'; import * as vscode from 'vscode'; -import { CppBuildTaskDefinition} from '../LanguageServer/cppbuildTaskProvider'; +import { CppBuildTaskDefinition} from '../LanguageServer/cppBuildTaskProvider'; import * as util from '../common'; import * as fs from 'fs'; import * as Telemetry from '../telemetry'; diff --git a/Extension/src/Debugger/extension.ts b/Extension/src/Debugger/extension.ts index baca62d98..a44081a9c 100644 --- a/Extension/src/Debugger/extension.ts +++ b/Extension/src/Debugger/extension.ts @@ -9,7 +9,7 @@ import { AttachPicker, RemoteAttachPicker, AttachItemsProvider } from './attachT import { NativeAttachItemsProviderFactory } from './nativeAttach'; import { QuickPickConfigurationProvider, ConfigurationAssetProviderFactory, CppVsDbgConfigurationProvider, CppDbgConfigurationProvider, ConfigurationSnippetProvider, IConfigurationAssetProvider } from './configurationProvider'; import { CppdbgDebugAdapterDescriptorFactory, CppvsdbgDebugAdapterDescriptorFactory } from './debugAdapterDescriptorFactory'; -import { failedToParseTasksJson } from '../LanguageServer/cppbuildTaskProvider'; +import { failedToParseTasksJson } from '../LanguageServer/cppBuildTaskProvider'; import * as util from '../common'; import * as Telemetry from '../telemetry'; import * as nls from 'vscode-nls'; diff --git a/Extension/src/LanguageServer/cppbuildTaskProvider.ts b/Extension/src/LanguageServer/cppbuildTaskProvider.ts index 215acad5b..22184423f 100644 --- a/Extension/src/LanguageServer/cppbuildTaskProvider.ts +++ b/Extension/src/LanguageServer/cppbuildTaskProvider.ts @@ -14,6 +14,7 @@ import * as fs from 'fs'; import * as nls from 'vscode-nls'; import * as cp from "child_process"; import { OtherSettings } from './settings'; +import * as jsonc from 'jsonc-parser'; const localize: nls.LocalizeFunc = nls.loadMessageBundle(); export const failedToParseTasksJson: string = localize("failed.to.parse.tasks", "Failed to parse tasks.json, possibly due to comments or trailing commas."); @@ -23,7 +24,7 @@ export interface CppBuildTaskDefinition extends vscode.TaskDefinition { label: string; command: string; args: string[]; - options: cp.ProcessEnvOptions | undefined; + options: cp.ExecOptions | undefined; } export class CppBuildTaskProvider implements vscode.TaskProvider { @@ -157,7 +158,7 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { if (!definition && compilerArgs && compilerArgs.length > 0) { args = args.concat(compilerArgs); } - const options: cp.ProcessEnvOptions | undefined = {"cwd": cwd}; + const options: cp.ExecOptions | undefined = {"cwd": cwd}; // Double-quote the command if it is not already double-quoted. let resolvedcompilerPath: string = isCl ? compilerPathBase : compilerPath; @@ -248,7 +249,7 @@ class CustomBuildTaskTerminal implements vscode.Pseudoterminal { private fileWatcher: vscode.FileSystemWatcher | undefined; - constructor(private command: string, private args: string[], private options: cp.ProcessEnvOptions | undefined, private workspaceRoot: string) { + constructor(private command: string, private args: string[], private options: cp.ExecOptions | undefined, private workspaceRoot: string) { } @@ -320,15 +321,14 @@ export function getRawTasksJson(): Promise { if (!path) { return resolve({}); } - fs.exists(path, exists => { + fs.exists(path, async exists => { if (!exists) { return resolve({}); } - let fileContents: string = fs.readFileSync(path).toString(); - fileContents = fileContents.replace(/^\s*\/\/.*$/gm, ""); // Remove start of line // comments. + let fileContents: string = await util.readFileText(path); let rawTasks: any = {}; try { - rawTasks = JSON.parse(fileContents); + rawTasks = jsonc.parse(fileContents); } catch (error) { return reject(new Error(failedToParseTasksJson)); } diff --git a/Extension/src/LanguageServer/extension.ts b/Extension/src/LanguageServer/extension.ts index d279690d2..831d5fc25 100644 --- a/Extension/src/LanguageServer/extension.ts +++ b/Extension/src/LanguageServer/extension.ts @@ -28,7 +28,7 @@ import * as rd from 'readline'; import * as yauzl from 'yauzl'; import { Readable, Writable } from 'stream'; import * as nls from 'vscode-nls'; -import { CppBuildTaskProvider } from './cppbuildTaskProvider'; +import { CppBuildTaskProvider } from './cppBuildTaskProvider'; nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })(); const localize: nls.LocalizeFunc = nls.loadMessageBundle(); From b2823b23e71dbd5effa61744dc474ca8b1f279c5 Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Tue, 23 Jun 2020 16:09:32 -0700 Subject: [PATCH 16/55] solving the error due to space in file name --- Extension/package.json | 3 ++- .../src/LanguageServer/cppbuildTaskProvider.ts | 18 +++++++++++++----- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/Extension/package.json b/Extension/package.json index 33defc502..9dacaf357 100644 --- a/Extension/package.json +++ b/Extension/package.json @@ -47,7 +47,8 @@ { "type": "cppbuild", "required": [ - "command" + "command", + "label" ], "properties": { "label": { diff --git a/Extension/src/LanguageServer/cppbuildTaskProvider.ts b/Extension/src/LanguageServer/cppbuildTaskProvider.ts index 22184423f..0a0e34cd0 100644 --- a/Extension/src/LanguageServer/cppbuildTaskProvider.ts +++ b/Extension/src/LanguageServer/cppbuildTaskProvider.ts @@ -158,7 +158,7 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { if (!definition && compilerArgs && compilerArgs.length > 0) { args = args.concat(compilerArgs); } - const options: cp.ExecOptions | undefined = {"cwd": cwd}; + const options: cp.ExecOptions | undefined = {cwd: cwd}; // Double-quote the command if it is not already double-quoted. let resolvedcompilerPath: string = isCl ? compilerPathBase : compilerPath; @@ -253,7 +253,7 @@ class CustomBuildTaskTerminal implements vscode.Pseudoterminal { } - open(initialDimensions: vscode.TerminalDimensions | undefined): void { + open(_initialDimensions: vscode.TerminalDimensions | undefined): void { telemetry.logLanguageServerEvent("cppBuildTaskStarted"); const pattern: string = path.join(this.workspaceRoot, 'cppBuild'); this.fileWatcher = vscode.workspace.createFileSystemWatcher(pattern); @@ -275,15 +275,22 @@ class CustomBuildTaskTerminal implements vscode.Pseudoterminal { private async doBuild(): Promise { return new Promise((resolve, reject) => { // Do build. - const activeCommand: string = util.resolveVariables(this.command + " " + this.args.join(" "), this.AdditionalEnvironment); + let activeCommand: string = util.resolveVariables(this.command, this.AdditionalEnvironment); + this.args.forEach(value => { + let temp: string = util.resolveVariables(value, this.AdditionalEnvironment); + if (temp && temp.includes(" ")) { + temp = "\"" + temp + "\""; + } + activeCommand = activeCommand + " " + temp; + }); if (this.options?.cwd) { this.options.cwd = util.resolveVariables(this.options.cwd, this.AdditionalEnvironment); } - cp.exec(activeCommand, this.options, (_error, stdout, stderr) => { + cp.exec(activeCommand, this.options, (_error, stdout, _stderr) => { if (_error) { telemetry.logLanguageServerEvent("cppBuildTaskError", { "error": _error.message }); this.writeEmitter.fire("Build finished with error:\r\n"); - this.writeEmitter.fire("\t" + _error.message + "\r\n"); + this.writeEmitter.fire(_error.message); reject(); } else { this.writeEmitter.fire(stdout.toString()); @@ -292,6 +299,7 @@ class CustomBuildTaskTerminal implements vscode.Pseudoterminal { } }); }).finally (() => { + this.writeEmitter.fire("\r\n"); this.closeEmitter.fire(); }); } From 62ff45946f23e66b91cc41d42d25804af56f8e71 Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Tue, 23 Jun 2020 16:27:36 -0700 Subject: [PATCH 17/55] showing the error message --- Extension/src/LanguageServer/cppbuildTaskProvider.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Extension/src/LanguageServer/cppbuildTaskProvider.ts b/Extension/src/LanguageServer/cppbuildTaskProvider.ts index 0a0e34cd0..904632b79 100644 --- a/Extension/src/LanguageServer/cppbuildTaskProvider.ts +++ b/Extension/src/LanguageServer/cppbuildTaskProvider.ts @@ -290,7 +290,7 @@ class CustomBuildTaskTerminal implements vscode.Pseudoterminal { if (_error) { telemetry.logLanguageServerEvent("cppBuildTaskError", { "error": _error.message }); this.writeEmitter.fire("Build finished with error:\r\n"); - this.writeEmitter.fire(_error.message); + this.writeEmitter.fire(stdout.toString()); reject(); } else { this.writeEmitter.fire(stdout.toString()); @@ -299,7 +299,6 @@ class CustomBuildTaskTerminal implements vscode.Pseudoterminal { } }); }).finally (() => { - this.writeEmitter.fire("\r\n"); this.closeEmitter.fire(); }); } From 4b2b34fc3386026ea5a565a801906b56b1d63b3d Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Thu, 2 Jul 2020 13:45:32 -0700 Subject: [PATCH 18/55] fix lint --- .../src/Debugger/configurationProvider.ts | 2 +- .../src/LanguageServer/cppbuildTaskProvider.ts | 18 +++++++++--------- Extension/src/LanguageServer/extension.ts | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Extension/src/Debugger/configurationProvider.ts b/Extension/src/Debugger/configurationProvider.ts index 56cc848c4..b2dc20eba 100644 --- a/Extension/src/Debugger/configurationProvider.ts +++ b/Extension/src/Debugger/configurationProvider.ts @@ -133,7 +133,7 @@ class CppConfigurationProvider implements vscode.DebugConfigurationProvider { // Generate new configurations for each build task. // Generating a task is async, therefore we must *await* *all* map(task => config) Promises to resolve. - let configs: vscode.DebugConfiguration[] = await Promise.all(buildTasks.map>(async task => { + const configs: vscode.DebugConfiguration[] = await Promise.all(buildTasks.map>(async task => { const definition: CppBuildTaskDefinition = task.definition as CppBuildTaskDefinition; const compilerPath: string = definition.command; const compilerName: string = path.basename(compilerPath); diff --git a/Extension/src/LanguageServer/cppbuildTaskProvider.ts b/Extension/src/LanguageServer/cppbuildTaskProvider.ts index 904632b79..cb5b6bf4d 100644 --- a/Extension/src/LanguageServer/cppbuildTaskProvider.ts +++ b/Extension/src/LanguageServer/cppbuildTaskProvider.ts @@ -176,8 +176,8 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { }; } - let activeClient: Client = ext.getActiveClient(); - let uri: vscode.Uri | undefined = activeClient.RootUri; + const activeClient: Client = ext.getActiveClient(); + const uri: vscode.Uri | undefined = activeClient.RootUri; if (!uri) { throw new Error("No client URI found in getBuildTasks()"); } @@ -186,7 +186,7 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { throw new Error("No target WorkspaceFolder found in getBuildTasks()"); } - let task: vscode.Task = new vscode.Task(definition, target, taskName, CppBuildTaskProvider.CppBuildSourceStr, + const task: vscode.Task = new vscode.Task(definition, target, taskName, CppBuildTaskProvider.CppBuildSourceStr, new vscode.CustomExecution(async (): Promise => // When the task is executed, this callback will run. Here, we setup for running the task. new CustomBuildTaskTerminal(resolvedcompilerPath, args, options, target.name) @@ -198,7 +198,7 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { }; async ensureBuildTaskExists(taskName: string): Promise { - let rawTasksJson: any = await getRawTasksJson(); + const rawTasksJson: any = await getRawTasksJson(); // Ensure that the task exists in the user's task.json. Task will not be found otherwise. if (!rawTasksJson.tasks) { @@ -219,9 +219,9 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { rawTasksJson.version = "2.0.0"; - let selectedTask2: vscode.Task = selectedTask; + const selectedTask2: vscode.Task = selectedTask; if (!rawTasksJson.tasks.find((task: any) => task.label === selectedTask2.definition.label)) { - let task: any = { + const task: any = { ...selectedTask2.definition, problemMatcher: selectedTask2.problemMatchers, group: { kind: "build", "isDefault": true } @@ -230,8 +230,8 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { } // TODO: It's dangerous to overwrite this file. We could be wiping out comments. - let settings: OtherSettings = new OtherSettings(); - let tasksJsonPath: string | undefined = getTasksJsonPath(); + const settings: OtherSettings = new OtherSettings(); + const tasksJsonPath: string | undefined = getTasksJsonPath(); if (!tasksJsonPath) { throw new Error("Failed to get tasksJsonPath in ensureBuildTaskExists()"); } @@ -332,7 +332,7 @@ export function getRawTasksJson(): Promise { if (!exists) { return resolve({}); } - let fileContents: string = await util.readFileText(path); + const fileContents: string = await util.readFileText(path); let rawTasks: any = {}; try { rawTasks = jsonc.parse(fileContents); diff --git a/Extension/src/LanguageServer/extension.ts b/Extension/src/LanguageServer/extension.ts index 4bffd3601..2585832c2 100644 --- a/Extension/src/LanguageServer/extension.ts +++ b/Extension/src/LanguageServer/extension.ts @@ -32,7 +32,7 @@ import { CppBuildTaskProvider } from './cppBuildTaskProvider'; nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })(); const localize: nls.LocalizeFunc = nls.loadMessageBundle(); -export let cppBuildTaskProvider: CppBuildTaskProvider = new CppBuildTaskProvider(); +export const cppBuildTaskProvider: CppBuildTaskProvider = new CppBuildTaskProvider(); let prevCrashFile: string; let clients: ClientCollection; From ce1b6477c52056f27fa9104e76074e178ffc2fd8 Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Sun, 5 Jul 2020 13:22:31 -0700 Subject: [PATCH 19/55] add set timeout and setinterval from timers --- Extension/src/LanguageServer/configurations.ts | 1 + Extension/src/LanguageServer/references.ts | 1 + Extension/src/LanguageServer/ui.ts | 1 + 3 files changed, 3 insertions(+) diff --git a/Extension/src/LanguageServer/configurations.ts b/Extension/src/LanguageServer/configurations.ts index e6033f805..ccc130a5d 100644 --- a/Extension/src/LanguageServer/configurations.ts +++ b/Extension/src/LanguageServer/configurations.ts @@ -17,6 +17,7 @@ import { SettingsPanel } from './settingsPanel'; import * as os from 'os'; import escapeStringRegExp = require('escape-string-regexp'); import * as nls from 'vscode-nls'; +import { setTimeout } from 'timers'; nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })(); const localize: nls.LocalizeFunc = nls.loadMessageBundle(); diff --git a/Extension/src/LanguageServer/references.ts b/Extension/src/LanguageServer/references.ts index 2174c4896..10d9333d8 100644 --- a/Extension/src/LanguageServer/references.ts +++ b/Extension/src/LanguageServer/references.ts @@ -11,6 +11,7 @@ import * as nls from 'vscode-nls'; import * as logger from '../logger'; import { PersistentState } from './persistentState'; import * as util from '../common'; +import { setInterval } from 'timers'; nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })(); const localize: nls.LocalizeFunc = nls.loadMessageBundle(); diff --git a/Extension/src/LanguageServer/ui.ts b/Extension/src/LanguageServer/ui.ts index d0c2e0856..9dadfd6ec 100644 --- a/Extension/src/LanguageServer/ui.ts +++ b/Extension/src/LanguageServer/ui.ts @@ -9,6 +9,7 @@ import { Client } from './client'; import { ReferencesCommandMode, referencesCommandModeToString } from './references'; import { getCustomConfigProviders, CustomConfigurationProviderCollection, isSameProviderExtensionId } from './customProviders'; import * as nls from 'vscode-nls'; +import { setTimeout } from 'timers'; nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })(); const localize: nls.LocalizeFunc = nls.loadMessageBundle(); From 9ebe69277a31fcf04699e60ca63a54d9e5c7fb93 Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Mon, 6 Jul 2020 10:11:08 -0700 Subject: [PATCH 20/55] Rename cppbuildTaskProvider.ts to cppBuildTaskProvider.ts --- .../{cppbuildTaskProvider.ts => cppBuildTaskProvider.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Extension/src/LanguageServer/{cppbuildTaskProvider.ts => cppBuildTaskProvider.ts} (100%) diff --git a/Extension/src/LanguageServer/cppbuildTaskProvider.ts b/Extension/src/LanguageServer/cppBuildTaskProvider.ts similarity index 100% rename from Extension/src/LanguageServer/cppbuildTaskProvider.ts rename to Extension/src/LanguageServer/cppBuildTaskProvider.ts From 8abef509c743e4a0ae11687401fb43fffd4c526d Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Tue, 7 Jul 2020 18:36:11 -0700 Subject: [PATCH 21/55] fire the events with zero --- Extension/src/LanguageServer/cppbuildTaskProvider.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Extension/src/LanguageServer/cppbuildTaskProvider.ts b/Extension/src/LanguageServer/cppbuildTaskProvider.ts index cb5b6bf4d..ec4e68e49 100644 --- a/Extension/src/LanguageServer/cppbuildTaskProvider.ts +++ b/Extension/src/LanguageServer/cppbuildTaskProvider.ts @@ -242,9 +242,9 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { class CustomBuildTaskTerminal implements vscode.Pseudoterminal { private writeEmitter = new vscode.EventEmitter(); - private closeEmitter = new vscode.EventEmitter(); + private closeEmitter = new vscode.EventEmitter(); public get onDidWrite(): vscode.Event { return this.writeEmitter.event; } - public get onDidClose(): vscode.Event { return this.closeEmitter.event; } + public get onDidClose(): vscode.Event { return this.closeEmitter.event; } private fileWatcher: vscode.FileSystemWatcher | undefined; @@ -272,8 +272,8 @@ class CustomBuildTaskTerminal implements vscode.Pseudoterminal { } } - private async doBuild(): Promise { - return new Promise((resolve, reject) => { + private async doBuild(): Promise { + return new Promise((resolve, reject) => { // Do build. let activeCommand: string = util.resolveVariables(this.command, this.AdditionalEnvironment); this.args.forEach(value => { @@ -295,11 +295,11 @@ class CustomBuildTaskTerminal implements vscode.Pseudoterminal { } else { this.writeEmitter.fire(stdout.toString()); this.writeEmitter.fire("\r\nBuild finished successfully.\r\n"); - resolve(); + resolve(0); } }); }).finally (() => { - this.closeEmitter.fire(); + this.closeEmitter.fire(0); }); } From 95258cbe448c32b203c2804b7719ac447ed5e304 Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Tue, 14 Jul 2020 00:51:47 -0700 Subject: [PATCH 22/55] delete filewatcher --- Extension/package.json | 2 +- .../src/LanguageServer/cppBuildTaskProvider.ts | 17 +++-------------- 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/Extension/package.json b/Extension/package.json index 22e5c72ac..f4ac784d1 100644 --- a/Extension/package.json +++ b/Extension/package.json @@ -61,7 +61,7 @@ }, "args": { "type": "array", - "description": "Additional build args." + "description": "Additional compiler args." }, "options": { "type": "object", diff --git a/Extension/src/LanguageServer/cppBuildTaskProvider.ts b/Extension/src/LanguageServer/cppBuildTaskProvider.ts index ec4e68e49..480acbddd 100644 --- a/Extension/src/LanguageServer/cppBuildTaskProvider.ts +++ b/Extension/src/LanguageServer/cppBuildTaskProvider.ts @@ -189,7 +189,7 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { const task: vscode.Task = new vscode.Task(definition, target, taskName, CppBuildTaskProvider.CppBuildSourceStr, new vscode.CustomExecution(async (): Promise => // When the task is executed, this callback will run. Here, we setup for running the task. - new CustomBuildTaskTerminal(resolvedcompilerPath, args, options, target.name) + new CustomBuildTaskTerminal(resolvedcompilerPath, args, options) ), isCl ? '$msCompile' : '$gcc'); task.group = vscode.TaskGroup.Build; @@ -246,20 +246,12 @@ class CustomBuildTaskTerminal implements vscode.Pseudoterminal { public get onDidWrite(): vscode.Event { return this.writeEmitter.event; } public get onDidClose(): vscode.Event { return this.closeEmitter.event; } - private fileWatcher: vscode.FileSystemWatcher | undefined; - - - constructor(private command: string, private args: string[], private options: cp.ExecOptions | undefined, private workspaceRoot: string) { + constructor(private command: string, private args: string[], private options: cp.ExecOptions | undefined) { } open(_initialDimensions: vscode.TerminalDimensions | undefined): void { telemetry.logLanguageServerEvent("cppBuildTaskStarted"); - const pattern: string = path.join(this.workspaceRoot, 'cppBuild'); - this.fileWatcher = vscode.workspace.createFileSystemWatcher(pattern); - this.fileWatcher.onDidChange(() => this.doBuild()); - this.fileWatcher.onDidCreate(() => this.doBuild()); - this.fileWatcher.onDidDelete(() => this.doBuild()); // At this point we can start using the terminal. this.writeEmitter.fire("Starting build...\r\n"); this.doBuild(); @@ -267,9 +259,6 @@ class CustomBuildTaskTerminal implements vscode.Pseudoterminal { close(): void { // The terminal has been closed. Shutdown the build. - if (this.fileWatcher) { - this.fileWatcher.dispose(); - } } private async doBuild(): Promise { @@ -288,7 +277,7 @@ class CustomBuildTaskTerminal implements vscode.Pseudoterminal { } cp.exec(activeCommand, this.options, (_error, stdout, _stderr) => { if (_error) { - telemetry.logLanguageServerEvent("cppBuildTaskError", { "error": _error.message }); + telemetry.logLanguageServerEvent("cppBuildTaskError"); this.writeEmitter.fire("Build finished with error:\r\n"); this.writeEmitter.fire(stdout.toString()); reject(); From 1182bb243b5bcef08c13f64e19f051f660670b8a Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Tue, 14 Jul 2020 14:56:35 -0700 Subject: [PATCH 23/55] localize strings --- Extension/package.json | 8 ++++---- Extension/package.nls.json | 6 +++++- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/Extension/package.json b/Extension/package.json index f4ac784d1..f40a38568 100644 --- a/Extension/package.json +++ b/Extension/package.json @@ -53,19 +53,19 @@ "properties": { "label": { "type": "string", - "description": "Task's name." + "description": "%c_cpp.taskDefinitions.name.description%" }, "command": { "type": "string", - "description": "The compiler path." + "description": "%c_cpp.taskDefinitions.command.description%" }, "args": { "type": "array", - "description": "Additional compiler args." + "description": "%c_cpp.taskDefinitions.args.description%" }, "options": { "type": "object", - "description": "Options" + "description": "%c_cpp.taskDefinitions.options.description%" } } } diff --git a/Extension/package.nls.json b/Extension/package.nls.json index 8e8228a00..feb7cbcd0 100644 --- a/Extension/package.nls.json +++ b/Extension/package.nls.json @@ -129,5 +129,9 @@ "c_cpp.debuggers.symbolLoadInfo.description": "Explicit control of symbol loading.", "c_cpp.debuggers.symbolLoadInfo.loadAll.description": "If true, symbols for all libs will be loaded, otherwise no solib symbols will be loaded. Default value is true.", "c_cpp.debuggers.symbolLoadInfo.exceptionList.description": "List of filenames (wildcards allowed) separated by semicolons ';'. Modifies behavior of LoadAll. If LoadAll is true then don't load symbols for libs that match any name in the list. Otherwise only load symbols for libs that match. Example: \"foo.so;bar.so\"", - "c_cpp.debuggers.requireExactSource.description": "Optional flag to require current source code to match the pdb." + "c_cpp.debuggers.requireExactSource.description": "Optional flag to require current source code to match the pdb.", + "c_cpp.taskDefinitions.name.description": "The name of the task.", + "c_cpp.taskDefinitions.command.description": "The path to either a compiler or script that performs compilation.", + "c_cpp.taskDefinitions.args.description": "Additional arguments to pass to the compiler or compilation script.", + "c_cpp.taskDefinitions.options.description": "Additional options including cwd and env." } From fa075fbc4d613f5156c6d1e2d51b1f2950354661 Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Tue, 14 Jul 2020 16:15:23 -0700 Subject: [PATCH 24/55] change changelog.md --- Extension/CHANGELOG.md | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/Extension/CHANGELOG.md b/Extension/CHANGELOG.md index 12d0ad987..04cc8e971 100644 --- a/Extension/CHANGELOG.md +++ b/Extension/CHANGELOG.md @@ -1,28 +1,16 @@ # C/C++ for Visual Studio Code Change Log -## Version 0.29.0-insiders2: July 8, 2020 +## Version 0.29.0: July 16, 2020 ### New Features -* Added support for LogMessage Breakpoints for debug type `cppdbg`. [#1013](https://github.com/microsoft/MIEngine/pull/1013) -* Switch to using the VS Code Semantic Tokens API for semantic colorization. [PR #5401](https://github.com/microsoft/vscode-cpptools/pull/5401) +* Add Doxygen comment support (to tooltip display of hover, completion, and signature help). [#658](https://github.com/microsoft/vscode-cpptools/issues/658) + * Add `C_Cpp.simplifyStructuredComments` setting. [#5706](https://github.com/microsoft/vscode-cpptools/issues/5706) +* Auto-convert `.` to `->` when the type is a pointer. [#862](https://github.com/microsoft/vscode-cpptools/issues/862) +* Switch to using the VS Code Semantic Tokens API for semantic colorization (works with remoting). [PR #5401](https://github.com/microsoft/vscode-cpptools/pull/5401), [#3932](https://github.com/microsoft/vscode-cpptools/issues/3932), [#3933](https://github.com/microsoft/vscode-cpptools/issues/3933), [#3942](https://github.com/microsoft/vscode-cpptools/issues/3942) +* Added support for LogMessage Breakpoints for debug type `cppdbg`. [MIEngine#1013](https://github.com/microsoft/MIEngine/pull/1013) ### Enhancements * Automatically add `"${default}"` to the default `includePath` in `c_cpp_properties.json` if `C_Cpp.default.includePath` is set. [#3733](https://github.com/microsoft/vscode-cpptools/issues/3733) -* Add `C_Cpp.simplifyStructuredComments` setting. [#5706](https://github.com/microsoft/vscode-cpptools/issues/5706) * Add configuration provider logging to `C/C++: Log Diagnostics`. [#4826](https://github.com/microsoft/vscode-cpptools/issues/4826) - -### Bug Fixes -* Ignore "screen size is bogus" error when debugging. [PR #5669](https://github.com/microsoft/vscode-cpptools/pull/5669) - * nukoyluoglu (@nukoyluoglu) -* Fix `compile_commands.json` sometimes not updating. [#5687](https://github.com/microsoft/vscode-cpptools/issues/5687) -* Add msys2 clang compilers to the compiler search list (previously only gcc was handled). [#5697](https://github.com/microsoft/vscode-cpptools/issues/5697) -* Fix extension getting stuck when an "@" response file that doesn't end with ".rsp" is used in `compilerArgs`. [#5731](https://github.com/microsoft/vscode-cpptools/issues/5731) -* Fix forced includes not handled properly when parsed as compiler args. [#5738](https://github.com/microsoft/vscode-cpptools/issues/5738) - -## Version 0.29.0-insiders: June 24, 2020 -### New Features -* Add Doxygen comment support (to tooltip display of hover, completion, and signature help). [#658](https://github.com/microsoft/vscode-cpptools/issues/658) - -### Enhancements * Add support for the Debug Welcome Panel. [#4837](https://github.com/microsoft/vscode-cpptools/issues/4837) * Update to clang-format 10. [#5194](https://github.com/microsoft/vscode-cpptools/issues/5194) * Added system to store and query properties from the active C/C++ configuration. @@ -30,6 +18,7 @@ * Add `quoteArgs` to `launch.json` schema. [PR #5639](https://github.com/microsoft/vscode-cpptools/pull/5639) * Add logs for a resolved `launch.json` if "engineLogging" is enabled. [PR #5644](https://github.com/microsoft/vscode-cpptools/pull/5644) * Add threadExit and processExit logging flags for 'cppvsdbg'. [PR #5652](https://github.com/microsoft/vscode-cpptools/pull/5652) +* Add support to run cpp build tasks (Tasks: Run Build Task) [#3674](https://github.com/microsoft/vscode-cpptools/issues/3674) ### Bug Fixes * Add localization support for autocomplete and hover text. [#5370](https://github.com/microsoft/vscode-cpptools/issues/5370) @@ -39,12 +28,18 @@ * Add gcc/gcc-10 compiler detection. [#5540](https://github.com/microsoft/vscode-cpptools/issues/5540) * Fix `--target` compiler arg getting overridden. [#5557](https://github.com/microsoft/vscode-cpptools/issues/5557) * Matt Schulte (@schultetwin1) -* Fix IntelliSense process crashes. [#5584](https://github.com/microsoft/vscode-cpptools/issues/5584), [#5629](https://github.com/microsoft/vscode-cpptools/issues/5629) * Fix Find All References and Rename when multiple references are on the same line. [#5568](https://github.com/microsoft/vscode-cpptools/issues/5568) +* Fix IntelliSense process crashes. [#5584](https://github.com/microsoft/vscode-cpptools/issues/5584), [#5629](https://github.com/microsoft/vscode-cpptools/issues/5629) * Fix an add/remove workspace folder crash. [#5591](https://github.com/microsoft/vscode-cpptools/issues/5591) * Fix default build tasks failing on Windows if the compiler isn't on the PATH. [#5604](https://github.com/microsoft/vscode-cpptools/issues/5604) * Fix updating `files.associations` and .C files being associated with C instead of C++. [#5618](https://github.com/microsoft/vscode-cpptools/issues/5618) * Fix IntelliSense malfunction when RxCpp is used. [#5619](https://github.com/microsoft/vscode-cpptools/issues/5619) +* Ignore "screen size is bogus" error when debugging. [PR #5669](https://github.com/microsoft/vscode-cpptools/pull/5669) + * nukoyluoglu (@nukoyluoglu) +* Fix `compile_commands.json` sometimes not updating. [#5687](https://github.com/microsoft/vscode-cpptools/issues/5687) +* Add msys2 clang compilers to the compiler search list (previously only gcc was handled). [#5697](https://github.com/microsoft/vscode-cpptools/issues/5697) +* Fix extension getting stuck when an "@" response file that doesn't end with ".rsp" is used in `compilerArgs`. [#5731](https://github.com/microsoft/vscode-cpptools/issues/5731) +* Fix forced includes not handled properly when parsed as compiler args. [#5738](https://github.com/microsoft/vscode-cpptools/issues/5738) * Fix potential thread deadlock in cpptools. * Fix copying a long value from debug watch results in pasting partial value [#5470](https://github.com/microsoft/vscode-cpptools/issues/5470) * [PR MIEngine#1009](https://github.com/microsoft/MIEngine/pull/1009) From 334b9e24fbf2250e6d05e58c48745a2bc24b09e4 Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Tue, 14 Jul 2020 16:20:53 -0700 Subject: [PATCH 25/55] changelog --- Extension/CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Extension/CHANGELOG.md b/Extension/CHANGELOG.md index 04cc8e971..d8ef60555 100644 --- a/Extension/CHANGELOG.md +++ b/Extension/CHANGELOG.md @@ -6,14 +6,14 @@ * Add `C_Cpp.simplifyStructuredComments` setting. [#5706](https://github.com/microsoft/vscode-cpptools/issues/5706) * Auto-convert `.` to `->` when the type is a pointer. [#862](https://github.com/microsoft/vscode-cpptools/issues/862) * Switch to using the VS Code Semantic Tokens API for semantic colorization (works with remoting). [PR #5401](https://github.com/microsoft/vscode-cpptools/pull/5401), [#3932](https://github.com/microsoft/vscode-cpptools/issues/3932), [#3933](https://github.com/microsoft/vscode-cpptools/issues/3933), [#3942](https://github.com/microsoft/vscode-cpptools/issues/3942) -* Added support for LogMessage Breakpoints for debug type `cppdbg`. [MIEngine#1013](https://github.com/microsoft/MIEngine/pull/1013) +* Add support for LogMessage Breakpoints for debug type `cppdbg`. [MIEngine#1013](https://github.com/microsoft/MIEngine/pull/1013) ### Enhancements * Automatically add `"${default}"` to the default `includePath` in `c_cpp_properties.json` if `C_Cpp.default.includePath` is set. [#3733](https://github.com/microsoft/vscode-cpptools/issues/3733) * Add configuration provider logging to `C/C++: Log Diagnostics`. [#4826](https://github.com/microsoft/vscode-cpptools/issues/4826) * Add support for the Debug Welcome Panel. [#4837](https://github.com/microsoft/vscode-cpptools/issues/4837) * Update to clang-format 10. [#5194](https://github.com/microsoft/vscode-cpptools/issues/5194) -* Added system to store and query properties from the active C/C++ configuration. +* Add system to store and query properties from the active C/C++ configuration. * bugengine (@bugengine) [PR #5453](https://github.com/microsoft/vscode-cpptools/pull/5453) * Add `quoteArgs` to `launch.json` schema. [PR #5639](https://github.com/microsoft/vscode-cpptools/pull/5639) * Add logs for a resolved `launch.json` if "engineLogging" is enabled. [PR #5644](https://github.com/microsoft/vscode-cpptools/pull/5644) From 4045b907be6e37b6e62af7cdfab97f5c76d0fb13 Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Tue, 14 Jul 2020 16:50:53 -0700 Subject: [PATCH 26/55] changelog --- Extension/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Extension/CHANGELOG.md b/Extension/CHANGELOG.md index d8ef60555..a87a0b099 100644 --- a/Extension/CHANGELOG.md +++ b/Extension/CHANGELOG.md @@ -1,6 +1,6 @@ # C/C++ for Visual Studio Code Change Log -## Version 0.29.0: July 16, 2020 +## Version 0.29.0: July 15, 2020 ### New Features * Add Doxygen comment support (to tooltip display of hover, completion, and signature help). [#658](https://github.com/microsoft/vscode-cpptools/issues/658) * Add `C_Cpp.simplifyStructuredComments` setting. [#5706](https://github.com/microsoft/vscode-cpptools/issues/5706) From 73b64c127e2388c648f90e45e6f2da71c24f5e2c Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Wed, 15 Jul 2020 07:01:10 -0700 Subject: [PATCH 27/55] change format --- Extension/CHANGELOG.md | 2 +- .../LanguageServer/cppBuildTaskProvider.ts | 30 +++++++++---------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Extension/CHANGELOG.md b/Extension/CHANGELOG.md index a87a0b099..ec9dc4758 100644 --- a/Extension/CHANGELOG.md +++ b/Extension/CHANGELOG.md @@ -3,7 +3,7 @@ ## Version 0.29.0: July 15, 2020 ### New Features * Add Doxygen comment support (to tooltip display of hover, completion, and signature help). [#658](https://github.com/microsoft/vscode-cpptools/issues/658) - * Add `C_Cpp.simplifyStructuredComments` setting. [#5706](https://github.com/microsoft/vscode-cpptools/issues/5706) + * The way comments are formatted is controlled by the C_Cpp.simplifyStructuredComments setting. * Auto-convert `.` to `->` when the type is a pointer. [#862](https://github.com/microsoft/vscode-cpptools/issues/862) * Switch to using the VS Code Semantic Tokens API for semantic colorization (works with remoting). [PR #5401](https://github.com/microsoft/vscode-cpptools/pull/5401), [#3932](https://github.com/microsoft/vscode-cpptools/issues/3932), [#3933](https://github.com/microsoft/vscode-cpptools/issues/3933), [#3942](https://github.com/microsoft/vscode-cpptools/issues/3942) * Add support for LogMessage Breakpoints for debug type `cppdbg`. [MIEngine#1013](https://github.com/microsoft/MIEngine/pull/1013) diff --git a/Extension/src/LanguageServer/cppBuildTaskProvider.ts b/Extension/src/LanguageServer/cppBuildTaskProvider.ts index 480acbddd..626b705e1 100644 --- a/Extension/src/LanguageServer/cppBuildTaskProvider.ts +++ b/Extension/src/LanguageServer/cppBuildTaskProvider.ts @@ -32,7 +32,7 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { static CppBuildSourceStr: string = "C/C++"; private tasks: vscode.Task[] | undefined; - constructor() {} + constructor() { } public async provideTasks(): Promise { if (this.tasks) { @@ -117,13 +117,13 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { // Get known compiler paths. Do not include the known compiler path that is the same as user compiler path. // Filter them based on the file type to get a reduced list appropriate for the active file. let knownCompilerPaths: string[] | undefined; - let knownCompilers: configs.KnownCompiler[] | undefined = await activeClient.getKnownCompilers(); + let knownCompilers: configs.KnownCompiler[] | undefined = await activeClient.getKnownCompilers(); if (knownCompilers) { knownCompilers = knownCompilers.filter(info => ((fileIsCpp && !info.isC) || (fileIsC && info.isC)) && - userCompilerPathAndArgs && - (path.basename(info.path) !== userCompilerPathAndArgs.compilerName) && - (!isWindows || !info.path.startsWith("/"))); // TODO: Add WSL compiler support. + userCompilerPathAndArgs && + (path.basename(info.path) !== userCompilerPathAndArgs.compilerName) && + (!isWindows || !info.path.startsWith("/"))); // TODO: Add WSL compiler support. knownCompilerPaths = knownCompilers.map(info => info.path); } @@ -137,7 +137,7 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { this.tasks = []; // Tasks for known compiler paths if (knownCompilerPaths) { - this.tasks = knownCompilerPaths.map(compilerPath => this.getTask(compilerPath, appendSourceToName, undefined)); + this.tasks = knownCompilerPaths.map(compilerPath => this.getTask(compilerPath, appendSourceToName, undefined)); } // Task for user compiler path setting if (userCompilerPath) { @@ -147,7 +147,7 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { return this.tasks; } - private getTask: (compilerPath: string, appendSourceToName: boolean, compilerArgs?: string [], definition?: CppBuildTaskDefinition) => vscode.Task = (compilerPath: string, appendSourceToName: boolean, compilerArgs?: string [], definition?: CppBuildTaskDefinition) => { + private getTask: (compilerPath: string, appendSourceToName: boolean, compilerArgs?: string[], definition?: CppBuildTaskDefinition) => vscode.Task = (compilerPath: string, appendSourceToName: boolean, compilerArgs?: string[], definition?: CppBuildTaskDefinition) => { const filePath: string = path.join('${fileDirname}', '${fileBasenameNoExtension}'); const compilerPathBase: string = path.basename(compilerPath); const taskName: string = (appendSourceToName ? CppBuildTaskProvider.CppBuildSourceStr + ": " : "") + compilerPathBase + " build active file"; @@ -158,7 +158,7 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { if (!definition && compilerArgs && compilerArgs.length > 0) { args = args.concat(compilerArgs); } - const options: cp.ExecOptions | undefined = {cwd: cwd}; + const options: cp.ExecOptions | undefined = { cwd: cwd }; // Double-quote the command if it is not already double-quoted. let resolvedcompilerPath: string = isCl ? compilerPathBase : compilerPath; @@ -186,10 +186,10 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { throw new Error("No target WorkspaceFolder found in getBuildTasks()"); } - const task: vscode.Task = new vscode.Task(definition, target, taskName, CppBuildTaskProvider.CppBuildSourceStr, + const task: vscode.Task = new vscode.Task(definition, target, taskName, CppBuildTaskProvider.CppBuildSourceStr, new vscode.CustomExecution(async (): Promise => - // When the task is executed, this callback will run. Here, we setup for running the task. - new CustomBuildTaskTerminal(resolvedcompilerPath, args, options) + // When the task is executed, this callback will run. Here, we setup for running the task. + new CustomBuildTaskTerminal(resolvedcompilerPath, args, options) ), isCl ? '$msCompile' : '$gcc'); task.group = vscode.TaskGroup.Build; @@ -241,7 +241,7 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { } class CustomBuildTaskTerminal implements vscode.Pseudoterminal { - private writeEmitter = new vscode.EventEmitter(); + private writeEmitter = new vscode.EventEmitter(); private closeEmitter = new vscode.EventEmitter(); public get onDidWrite(): vscode.Event { return this.writeEmitter.event; } public get onDidClose(): vscode.Event { return this.closeEmitter.event; } @@ -249,7 +249,6 @@ class CustomBuildTaskTerminal implements vscode.Pseudoterminal { constructor(private command: string, private args: string[], private options: cp.ExecOptions | undefined) { } - open(_initialDimensions: vscode.TerminalDimensions | undefined): void { telemetry.logLanguageServerEvent("cppBuildTaskStarted"); // At this point we can start using the terminal. @@ -287,7 +286,7 @@ class CustomBuildTaskTerminal implements vscode.Pseudoterminal { resolve(0); } }); - }).finally (() => { + }).finally(() => { this.closeEmitter.fire(0); }); } @@ -307,7 +306,8 @@ class CustomBuildTaskTerminal implements vscode.Pseudoterminal { "file": file, "fileDirname": fileDir.uri.fsPath, "fileBasenameNoExtension": path.parse(file).name, - "workspaceFolder": fileDir.uri.fsPath}; + "workspaceFolder": fileDir.uri.fsPath + }; } } From e3703cbb92be894c7483a293993b12b96726b830 Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Wed, 15 Jul 2020 08:45:55 -0700 Subject: [PATCH 28/55] wait dobuild --- .../LanguageServer/cppBuildTaskProvider.ts | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/Extension/src/LanguageServer/cppBuildTaskProvider.ts b/Extension/src/LanguageServer/cppBuildTaskProvider.ts index 626b705e1..e3bc2b355 100644 --- a/Extension/src/LanguageServer/cppBuildTaskProvider.ts +++ b/Extension/src/LanguageServer/cppBuildTaskProvider.ts @@ -249,31 +249,31 @@ class CustomBuildTaskTerminal implements vscode.Pseudoterminal { constructor(private command: string, private args: string[], private options: cp.ExecOptions | undefined) { } - open(_initialDimensions: vscode.TerminalDimensions | undefined): void { + async open(_initialDimensions: vscode.TerminalDimensions | undefined): Promise { telemetry.logLanguageServerEvent("cppBuildTaskStarted"); // At this point we can start using the terminal. this.writeEmitter.fire("Starting build...\r\n"); - this.doBuild(); + await this.doBuild(); } close(): void { // The terminal has been closed. Shutdown the build. } - private async doBuild(): Promise { - return new Promise((resolve, reject) => { - // Do build. - let activeCommand: string = util.resolveVariables(this.command, this.AdditionalEnvironment); - this.args.forEach(value => { - let temp: string = util.resolveVariables(value, this.AdditionalEnvironment); - if (temp && temp.includes(" ")) { - temp = "\"" + temp + "\""; - } - activeCommand = activeCommand + " " + temp; - }); - if (this.options?.cwd) { - this.options.cwd = util.resolveVariables(this.options.cwd, this.AdditionalEnvironment); + private async doBuild(): Promise { + // Do build. + let activeCommand: string = util.resolveVariables(this.command, this.AdditionalEnvironment); + this.args.forEach(value => { + let temp: string = util.resolveVariables(value, this.AdditionalEnvironment); + if (temp && temp.includes(" ")) { + temp = "\"" + temp + "\""; } + activeCommand = activeCommand + " " + temp; + }); + if (this.options?.cwd) { + this.options.cwd = util.resolveVariables(this.options.cwd, this.AdditionalEnvironment); + } + await new Promise((resolve, reject) => { cp.exec(activeCommand, this.options, (_error, stdout, _stderr) => { if (_error) { telemetry.logLanguageServerEvent("cppBuildTaskError"); @@ -283,7 +283,7 @@ class CustomBuildTaskTerminal implements vscode.Pseudoterminal { } else { this.writeEmitter.fire(stdout.toString()); this.writeEmitter.fire("\r\nBuild finished successfully.\r\n"); - resolve(0); + resolve(); } }); }).finally(() => { From 752b0b6984332576f4082a4a7c2376406f492575 Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Wed, 15 Jul 2020 08:50:09 -0700 Subject: [PATCH 29/55] use checkFileExists --- Extension/src/LanguageServer/cppBuildTaskProvider.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Extension/src/LanguageServer/cppBuildTaskProvider.ts b/Extension/src/LanguageServer/cppBuildTaskProvider.ts index e3bc2b355..5ba9ac3af 100644 --- a/Extension/src/LanguageServer/cppBuildTaskProvider.ts +++ b/Extension/src/LanguageServer/cppBuildTaskProvider.ts @@ -317,10 +317,7 @@ export function getRawTasksJson(): Promise { if (!path) { return resolve({}); } - fs.exists(path, async exists => { - if (!exists) { - return resolve({}); - } + util.checkFileExists(path).then(async () => { const fileContents: string = await util.readFileText(path); let rawTasks: any = {}; try { @@ -329,6 +326,8 @@ export function getRawTasksJson(): Promise { return reject(new Error(failedToParseTasksJson)); } resolve(rawTasks); + }).catch(() => { + resolve({}); }); }); } From d30ce91a61cb7a4e6c15cddae14050f228a85261 Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Wed, 15 Jul 2020 08:53:00 -0700 Subject: [PATCH 30/55] after test --- Extension/src/LanguageServer/cppBuildTaskProvider.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/Extension/src/LanguageServer/cppBuildTaskProvider.ts b/Extension/src/LanguageServer/cppBuildTaskProvider.ts index 5ba9ac3af..edf3dd864 100644 --- a/Extension/src/LanguageServer/cppBuildTaskProvider.ts +++ b/Extension/src/LanguageServer/cppBuildTaskProvider.ts @@ -10,7 +10,6 @@ import * as telemetry from '../telemetry'; import { Client } from './client'; import * as configs from './configurations'; import * as ext from './extension'; -import * as fs from 'fs'; import * as nls from 'vscode-nls'; import * as cp from "child_process"; import { OtherSettings } from './settings'; From 0e9156501a85fb526c26705eb1483317fe67b31b Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Wed, 15 Jul 2020 09:05:41 -0700 Subject: [PATCH 31/55] after test2 --- Extension/src/LanguageServer/cppBuildTaskProvider.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Extension/src/LanguageServer/cppBuildTaskProvider.ts b/Extension/src/LanguageServer/cppBuildTaskProvider.ts index edf3dd864..97f9e98cb 100644 --- a/Extension/src/LanguageServer/cppBuildTaskProvider.ts +++ b/Extension/src/LanguageServer/cppBuildTaskProvider.ts @@ -325,9 +325,7 @@ export function getRawTasksJson(): Promise { return reject(new Error(failedToParseTasksJson)); } resolve(rawTasks); - }).catch(() => { - resolve({}); - }); + }).catch(() => { resolve({}); }); }); } From 4e6f53d75283dea5e8b5f57799975f38b489bbfd Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Wed, 15 Jul 2020 09:38:03 -0700 Subject: [PATCH 32/55] add properties --- Extension/package.json | 8 +++++++- Extension/package.nls.json | 3 ++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/Extension/package.json b/Extension/package.json index 6e4534c79..7c84a03c9 100644 --- a/Extension/package.json +++ b/Extension/package.json @@ -65,7 +65,13 @@ }, "options": { "type": "object", - "description": "%c_cpp.taskDefinitions.options.description%" + "description": "%c_cpp.taskDefinitions.options.description%", + "properties": { + "cwd": { + "type": "string", + "description": "%c_cpp.taskDefinitions.options.cwd.description%" + } + } } } } diff --git a/Extension/package.nls.json b/Extension/package.nls.json index c86702a53..f8cc1791e 100644 --- a/Extension/package.nls.json +++ b/Extension/package.nls.json @@ -134,5 +134,6 @@ "c_cpp.taskDefinitions.name.description": "The name of the task.", "c_cpp.taskDefinitions.command.description": "The path to either a compiler or script that performs compilation.", "c_cpp.taskDefinitions.args.description": "Additional arguments to pass to the compiler or compilation script.", - "c_cpp.taskDefinitions.options.description": "Additional options including cwd and env." + "c_cpp.taskDefinitions.options.description": "Additional command options.", + "c_cpp.taskDefinitions.options.cwd.description": "The current working directory of the executed program or script. If omitted Code's current workspace root is used." } From 4b1fbf504847ca190dc7263c892960e377eb8228 Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Wed, 15 Jul 2020 14:08:30 -0700 Subject: [PATCH 33/55] change the doBuild --- .../LanguageServer/cppBuildTaskProvider.ts | 68 ++++++++++--------- 1 file changed, 37 insertions(+), 31 deletions(-) diff --git a/Extension/src/LanguageServer/cppBuildTaskProvider.ts b/Extension/src/LanguageServer/cppBuildTaskProvider.ts index 97f9e98cb..08341ca68 100644 --- a/Extension/src/LanguageServer/cppBuildTaskProvider.ts +++ b/Extension/src/LanguageServer/cppBuildTaskProvider.ts @@ -272,22 +272,27 @@ class CustomBuildTaskTerminal implements vscode.Pseudoterminal { if (this.options?.cwd) { this.options.cwd = util.resolveVariables(this.options.cwd, this.AdditionalEnvironment); } - await new Promise((resolve, reject) => { - cp.exec(activeCommand, this.options, (_error, stdout, _stderr) => { - if (_error) { - telemetry.logLanguageServerEvent("cppBuildTaskError"); - this.writeEmitter.fire("Build finished with error:\r\n"); - this.writeEmitter.fire(stdout.toString()); - reject(); - } else { - this.writeEmitter.fire(stdout.toString()); - this.writeEmitter.fire("\r\nBuild finished successfully.\r\n"); - resolve(); - } + + try { + await new Promise((resolve, reject) => { + cp.exec(activeCommand, this.options, (_error, stdout, _stderr) => { + if (_error) { + telemetry.logLanguageServerEvent("cppBuildTaskError"); + const endOfLine: string = stdout ? ":" : "."; + this.writeEmitter.fire("Build finished with error" + endOfLine + "\r\n"); + this.writeEmitter.fire(stdout.toString()); + resolve(-1); + } else { + this.writeEmitter.fire(stdout.toString()); + this.writeEmitter.fire("\r\nBuild finished successfully.\r\n"); + resolve(0); + } + }); }); - }).finally(() => { this.closeEmitter.fire(0); - }); + } catch { + this.closeEmitter.fire(-1); + } } private get AdditionalEnvironment(): { [key: string]: string | string[] } | undefined { @@ -310,23 +315,24 @@ class CustomBuildTaskTerminal implements vscode.Pseudoterminal { } } -export function getRawTasksJson(): Promise { - return new Promise((resolve, reject) => { - const path: string | undefined = getTasksJsonPath(); - if (!path) { - return resolve({}); - } - util.checkFileExists(path).then(async () => { - const fileContents: string = await util.readFileText(path); - let rawTasks: any = {}; - try { - rawTasks = jsonc.parse(fileContents); - } catch (error) { - return reject(new Error(failedToParseTasksJson)); - } - resolve(rawTasks); - }).catch(() => { resolve({}); }); - }); +export async function getRawTasksJson(): Promise { + const path: string | undefined = getTasksJsonPath(); + if (!path) { + return {}; + } + const fileExists: boolean = await util.checkFileExists(path); + if (!fileExists) { + return {}; + } + + const fileContents: string = await util.readFileText(path); + let rawTasks: any = {}; + try { + rawTasks = jsonc.parse(fileContents); + } catch (error) { + throw new Error(failedToParseTasksJson); + } + return rawTasks; } export function getTasksJsonPath(): string | undefined { From c0026f9d3bb4c53a342919aa524d120792ad76fe Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Wed, 15 Jul 2020 14:52:19 -0700 Subject: [PATCH 34/55] this.closeEmitter.fire(result); --- Extension/src/LanguageServer/cppBuildTaskProvider.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Extension/src/LanguageServer/cppBuildTaskProvider.ts b/Extension/src/LanguageServer/cppBuildTaskProvider.ts index 08341ca68..3ce5e30f7 100644 --- a/Extension/src/LanguageServer/cppBuildTaskProvider.ts +++ b/Extension/src/LanguageServer/cppBuildTaskProvider.ts @@ -274,12 +274,11 @@ class CustomBuildTaskTerminal implements vscode.Pseudoterminal { } try { - await new Promise((resolve, reject) => { + const result: number = await new Promise((resolve, reject) => { cp.exec(activeCommand, this.options, (_error, stdout, _stderr) => { if (_error) { telemetry.logLanguageServerEvent("cppBuildTaskError"); - const endOfLine: string = stdout ? ":" : "."; - this.writeEmitter.fire("Build finished with error" + endOfLine + "\r\n"); + this.writeEmitter.fire("Build finished with error:\r\n"); this.writeEmitter.fire(stdout.toString()); resolve(-1); } else { @@ -289,7 +288,7 @@ class CustomBuildTaskTerminal implements vscode.Pseudoterminal { } }); }); - this.closeEmitter.fire(0); + this.closeEmitter.fire(result); } catch { this.closeEmitter.fire(-1); } From 66644da3d07b0436e52caf3fe8001c0e61754603 Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Wed, 15 Jul 2020 15:12:15 -0700 Subject: [PATCH 35/55] change doBuild --- Extension/src/LanguageServer/cppBuildTaskProvider.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Extension/src/LanguageServer/cppBuildTaskProvider.ts b/Extension/src/LanguageServer/cppBuildTaskProvider.ts index 3ce5e30f7..71731047b 100644 --- a/Extension/src/LanguageServer/cppBuildTaskProvider.ts +++ b/Extension/src/LanguageServer/cppBuildTaskProvider.ts @@ -276,14 +276,20 @@ class CustomBuildTaskTerminal implements vscode.Pseudoterminal { try { const result: number = await new Promise((resolve, reject) => { cp.exec(activeCommand, this.options, (_error, stdout, _stderr) => { + const endOfLine: string = os.platform() === 'win32' ? "\r\n" : "\n"; if (_error) { telemetry.logLanguageServerEvent("cppBuildTaskError"); - this.writeEmitter.fire("Build finished with error:\r\n"); + const dot: string = (stdout || _stderr) ? ":" : "."; + this.writeEmitter.fire("Build finished with error" + dot + endOfLine); this.writeEmitter.fire(stdout.toString()); + for (const line of _stderr.toString().split('\n')) { + this.writeEmitter.fire(line); + this.writeEmitter.fire(endOfLine); + } resolve(-1); } else { this.writeEmitter.fire(stdout.toString()); - this.writeEmitter.fire("\r\nBuild finished successfully.\r\n"); + this.writeEmitter.fire(endOfLine + "Build finished successfully." + endOfLine); resolve(0); } }); From 7ac3a29f10e44ce1fa59e5d17f4ad6f42692c246 Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Wed, 15 Jul 2020 15:25:01 -0700 Subject: [PATCH 36/55] very minor change --- Extension/src/LanguageServer/cppBuildTaskProvider.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Extension/src/LanguageServer/cppBuildTaskProvider.ts b/Extension/src/LanguageServer/cppBuildTaskProvider.ts index 71731047b..52f7a0525 100644 --- a/Extension/src/LanguageServer/cppBuildTaskProvider.ts +++ b/Extension/src/LanguageServer/cppBuildTaskProvider.ts @@ -282,7 +282,7 @@ class CustomBuildTaskTerminal implements vscode.Pseudoterminal { const dot: string = (stdout || _stderr) ? ":" : "."; this.writeEmitter.fire("Build finished with error" + dot + endOfLine); this.writeEmitter.fire(stdout.toString()); - for (const line of _stderr.toString().split('\n')) { + for (const line of _stderr.toString().split(endOfLine)) { this.writeEmitter.fire(line); this.writeEmitter.fire(endOfLine); } From bc9a05ae0e61771df2b9a557a2eee6bd649a8b47 Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Thu, 6 Aug 2020 16:45:50 -0400 Subject: [PATCH 37/55] label vs name resolved --- .../src/LanguageServer/cppBuildTaskProvider.ts | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/Extension/src/LanguageServer/cppBuildTaskProvider.ts b/Extension/src/LanguageServer/cppBuildTaskProvider.ts index 52f7a0525..22758fa76 100644 --- a/Extension/src/LanguageServer/cppBuildTaskProvider.ts +++ b/Extension/src/LanguageServer/cppBuildTaskProvider.ts @@ -20,7 +20,7 @@ export const failedToParseTasksJson: string = localize("failed.to.parse.tasks", export interface CppBuildTaskDefinition extends vscode.TaskDefinition { type: string; - label: string; + label: string; // The label appears in tasks.json file. command: string; args: string[]; options: cp.ExecOptions | undefined; @@ -149,7 +149,8 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { private getTask: (compilerPath: string, appendSourceToName: boolean, compilerArgs?: string[], definition?: CppBuildTaskDefinition) => vscode.Task = (compilerPath: string, appendSourceToName: boolean, compilerArgs?: string[], definition?: CppBuildTaskDefinition) => { const filePath: string = path.join('${fileDirname}', '${fileBasenameNoExtension}'); const compilerPathBase: string = path.basename(compilerPath); - const taskName: string = (appendSourceToName ? CppBuildTaskProvider.CppBuildSourceStr + ": " : "") + compilerPathBase + " build active file"; + const taskLabel: string = (appendSourceToName ? CppBuildTaskProvider.CppBuildSourceStr + ": " : "") + compilerPathBase + " build active file"; + const taskName: string = "Build with " + compilerPathBase + "."; const isCl: boolean = compilerPathBase === "cl.exe"; const isWindows: boolean = os.platform() === 'win32'; const cwd: string = isCl ? "${workspaceFolder}" : path.dirname(compilerPath); @@ -180,12 +181,13 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { if (!uri) { throw new Error("No client URI found in getBuildTasks()"); } - const target: vscode.WorkspaceFolder | undefined = vscode.workspace.getWorkspaceFolder(uri); - if (!target) { + //const scope: vscode.WorkspaceFolder | undefined = vscode.workspace.getWorkspaceFolder(uri); + const scope: vscode.TaskScope = vscode.TaskScope.Workspace; + if (!scope) { throw new Error("No target WorkspaceFolder found in getBuildTasks()"); } - const task: vscode.Task = new vscode.Task(definition, target, taskName, CppBuildTaskProvider.CppBuildSourceStr, + const task: vscode.Task = new vscode.Task(definition, scope, taskLabel, CppBuildTaskProvider.CppBuildSourceStr, new vscode.CustomExecution(async (): Promise => // When the task is executed, this callback will run. Here, we setup for running the task. new CustomBuildTaskTerminal(resolvedcompilerPath, args, options) @@ -196,7 +198,7 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { return task; }; - async ensureBuildTaskExists(taskName: string): Promise { + async ensureBuildTaskExists(taskLabel: string): Promise { const rawTasksJson: any = await getRawTasksJson(); // Ensure that the task exists in the user's task.json. Task will not be found otherwise. @@ -204,13 +206,13 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { rawTasksJson.tasks = new Array(); } // Find or create the task which should be created based on the selected "debug configuration". - let selectedTask: vscode.Task | undefined = rawTasksJson.tasks.find((task: any) => task.label && task.label === taskName); + let selectedTask: vscode.Task | undefined = rawTasksJson.tasks.find((task: any) => task.label && task.label === taskLabel); if (selectedTask) { return; } const buildTasks: vscode.Task[] = await this.getTasks(true); - selectedTask = buildTasks.find(task => task.name === taskName); + selectedTask = buildTasks.find(task => task.name === taskLabel); console.assert(selectedTask); if (!selectedTask) { throw new Error("Failed to get selectedTask in ensureBuildTaskExists()"); From 805412bb81281e9146ac7dc5e3d5cab1cb3d1a95 Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Mon, 10 Aug 2020 10:41:55 -0400 Subject: [PATCH 38/55] draft --- .../LanguageServer/cppBuildTaskProvider.ts | 31 +++++++++++++++++++ Extension/src/LanguageServer/extension.ts | 4 +-- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/Extension/src/LanguageServer/cppBuildTaskProvider.ts b/Extension/src/LanguageServer/cppBuildTaskProvider.ts index 22758fa76..5fdcdf9c6 100644 --- a/Extension/src/LanguageServer/cppBuildTaskProvider.ts +++ b/Extension/src/LanguageServer/cppBuildTaskProvider.ts @@ -26,6 +26,37 @@ export interface CppBuildTaskDefinition extends vscode.TaskDefinition { options: cp.ExecOptions | undefined; } +export class QuickPickCppBuildTaskProvider implements vscode.TaskProvider { + private underlyingTaskProvider: vscode.TaskProvider; + + public constructor(taskProvider: CppBuildTaskProvider) { + this.underlyingTaskProvider = taskProvider; + } + + public async provideTasks(): Promise { + let tasks: vscode.Task[] | undefined | null = this.underlyingTaskProvider.provideTasks ? + await this.underlyingTaskProvider.provideTasks() : undefined; + if (!tasks) { + tasks = []; + } + interface MenueItem extends vscode.QuickPickItem { + taskItem: vscode.Task; + } + const taskItems: MenueItem[] = tasks.map(task => { + const item: MenueItem = { label: "hello", taskItem: task, description: "cheers" }; + return item; + }); + const selectedTask: MenueItem | undefined = await vscode.window.showQuickPick(taskItems, {placeHolder: localize("select.configuration", "Select a task to configure")} ); + if (!selectedTask) { + throw new Error(); + } + return [selectedTask.taskItem]; + } + + public resolveTask(_task: vscode.Task): vscode.Task | undefined { + return undefined; + } +} export class CppBuildTaskProvider implements vscode.TaskProvider { static CppBuildScriptType: string = 'cppbuild'; static CppBuildSourceStr: string = "C/C++"; diff --git a/Extension/src/LanguageServer/extension.ts b/Extension/src/LanguageServer/extension.ts index 5e90b367e..bc7d22f22 100644 --- a/Extension/src/LanguageServer/extension.ts +++ b/Extension/src/LanguageServer/extension.ts @@ -28,7 +28,7 @@ import * as rd from 'readline'; import * as yauzl from 'yauzl'; import { Readable, Writable } from 'stream'; import * as nls from 'vscode-nls'; -import { CppBuildTaskProvider } from './cppBuildTaskProvider'; +import { CppBuildTaskProvider, QuickPickCppBuildTaskProvider } from './cppBuildTaskProvider'; nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })(); const localize: nls.LocalizeFunc = nls.loadMessageBundle(); @@ -171,7 +171,7 @@ export function activate(activationEventOccurred: boolean): void { return; } - taskProvider = vscode.tasks.registerTaskProvider(CppBuildTaskProvider.CppBuildScriptType, cppBuildTaskProvider); + taskProvider = vscode.tasks.registerTaskProvider(CppBuildTaskProvider.CppBuildScriptType, new QuickPickCppBuildTaskProvider(cppBuildTaskProvider)); vscode.tasks.onDidStartTask(event => { if (event.execution.task.source === CppBuildTaskProvider.CppBuildSourceStr) { From 4ae2bd41b55809a8e918b28337112217b7e95118 Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Mon, 10 Aug 2020 15:45:34 -0400 Subject: [PATCH 39/55] draft for Sean --- .../LanguageServer/cppBuildTaskProvider.ts | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/Extension/src/LanguageServer/cppBuildTaskProvider.ts b/Extension/src/LanguageServer/cppBuildTaskProvider.ts index 5fdcdf9c6..326f16698 100644 --- a/Extension/src/LanguageServer/cppBuildTaskProvider.ts +++ b/Extension/src/LanguageServer/cppBuildTaskProvider.ts @@ -46,7 +46,7 @@ export class QuickPickCppBuildTaskProvider implements vscode.TaskProvider { const item: MenueItem = { label: "hello", taskItem: task, description: "cheers" }; return item; }); - const selectedTask: MenueItem | undefined = await vscode.window.showQuickPick(taskItems, {placeHolder: localize("select.configuration", "Select a task to configure")} ); + const selectedTask: MenueItem | undefined = await vscode.window.showQuickPick(taskItems, { placeHolder: localize("select.configuration", "Select a task to configure") }); if (!selectedTask) { throw new Error(); } @@ -87,20 +87,21 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { return this.tasks; } const editor: vscode.TextEditor | undefined = vscode.window.activeTextEditor; + let emptyTasks: vscode.Task[] = []; if (!editor) { - return []; + return emptyTasks; } const fileExt: string = path.extname(editor.document.fileName); if (!fileExt) { - return []; + return emptyTasks; } // Don't offer tasks for header files. const fileExtLower: string = fileExt.toLowerCase(); const isHeader: boolean = !fileExt || [".hpp", ".hh", ".hxx", ".h++", ".hp", ".h", ".ii", ".inl", ".idl", ""].some(ext => fileExtLower === ext); if (isHeader) { - return []; + return emptyTasks; } // Don't offer tasks if the active file's extension is not a recognized C/C++ extension. @@ -114,7 +115,7 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { fileIsC = fileExtLower === ".c"; } if (!(fileIsCpp || fileIsC)) { - return []; + return emptyTasks; } // Get compiler paths. @@ -126,7 +127,7 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { if (!e || e.message !== ext.intelliSenseDisabledError) { console.error("Unknown error calling getActiveClient()."); } - return []; // Language service features may be disabled. + return emptyTasks; // Language service features may be disabled. } // Get user compiler path. @@ -160,21 +161,22 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { if (!knownCompilerPaths && !userCompilerPath) { // Don't prompt a message yet until we can make a data-based decision. telemetry.logLanguageServerEvent('noCompilerFound'); - return []; + return emptyTasks; } // Create a build task per compiler path - this.tasks = []; + //this.tasks = []; + let result: vscode.Task[] = []; // Tasks for known compiler paths if (knownCompilerPaths) { - this.tasks = knownCompilerPaths.map(compilerPath => this.getTask(compilerPath, appendSourceToName, undefined)); + result = knownCompilerPaths.map(compilerPath => this.getTask(compilerPath, appendSourceToName, undefined)); } // Task for user compiler path setting if (userCompilerPath) { - this.tasks.push(this.getTask(userCompilerPath, appendSourceToName, userCompilerPathAndArgs?.additionalArgs)); + result.push(this.getTask(userCompilerPath, appendSourceToName, userCompilerPathAndArgs?.additionalArgs)); } - return this.tasks; + return result; } private getTask: (compilerPath: string, appendSourceToName: boolean, compilerArgs?: string[], definition?: CppBuildTaskDefinition) => vscode.Task = (compilerPath: string, appendSourceToName: boolean, compilerArgs?: string[], definition?: CppBuildTaskDefinition) => { From 3a785e5b82b23336ae0cb1f36bccb137bf523aca Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Tue, 11 Aug 2020 12:18:22 -0400 Subject: [PATCH 40/55] before cleaning the code --- Extension/package.json | 4 + .../LanguageServer/cppBuildTaskProvider.ts | 87 ++++++++++--------- Extension/src/LanguageServer/extension.ts | 3 +- 3 files changed, 52 insertions(+), 42 deletions(-) diff --git a/Extension/package.json b/Extension/package.json index da2b7f26d..6de7d1449 100644 --- a/Extension/package.json +++ b/Extension/package.json @@ -55,6 +55,10 @@ "type": "string", "description": "%c_cpp.taskDefinitions.name.description%" }, + "description": { + "type": "string", + "description": "description of the task." + }, "command": { "type": "string", "description": "%c_cpp.taskDefinitions.command.description%" diff --git a/Extension/src/LanguageServer/cppBuildTaskProvider.ts b/Extension/src/LanguageServer/cppBuildTaskProvider.ts index 326f16698..1897c2e08 100644 --- a/Extension/src/LanguageServer/cppBuildTaskProvider.ts +++ b/Extension/src/LanguageServer/cppBuildTaskProvider.ts @@ -3,7 +3,10 @@ * See 'LICENSE' in the project root for license information. * ------------------------------------------------------------------------------------------ */ import * as path from 'path'; -import * as vscode from 'vscode'; +import { + TaskDefinition, Task, TaskGroup, WorkspaceFolder, ShellExecution, Uri, workspace, + TaskProvider, TaskScope, QuickPickItem, CustomExecution, ProcessExecution, TextEditor, Pseudoterminal, EventEmitter, Event, TerminalDimensions, window +} from 'vscode'; import * as os from 'os'; import * as util from '../common'; import * as telemetry from '../telemetry'; @@ -18,53 +21,54 @@ import * as jsonc from 'jsonc-parser'; const localize: nls.LocalizeFunc = nls.loadMessageBundle(); export const failedToParseTasksJson: string = localize("failed.to.parse.tasks", "Failed to parse tasks.json, possibly due to comments or trailing commas."); -export interface CppBuildTaskDefinition extends vscode.TaskDefinition { +export interface CppBuildTaskDefinition extends TaskDefinition { type: string; label: string; // The label appears in tasks.json file. + description: string; command: string; args: string[]; options: cp.ExecOptions | undefined; } -export class QuickPickCppBuildTaskProvider implements vscode.TaskProvider { - private underlyingTaskProvider: vscode.TaskProvider; +export class QuickPickCppBuildTaskProvider implements TaskProvider { + private underlyingTaskProvider: TaskProvider; public constructor(taskProvider: CppBuildTaskProvider) { this.underlyingTaskProvider = taskProvider; } - public async provideTasks(): Promise { - let tasks: vscode.Task[] | undefined | null = this.underlyingTaskProvider.provideTasks ? + public async provideTasks(): Promise { + let tasks: Task[] | undefined | null = this.underlyingTaskProvider.provideTasks ? await this.underlyingTaskProvider.provideTasks() : undefined; if (!tasks) { tasks = []; } - interface MenueItem extends vscode.QuickPickItem { - taskItem: vscode.Task; + interface MenueItem extends QuickPickItem { + taskItem: Task; } const taskItems: MenueItem[] = tasks.map(task => { const item: MenueItem = { label: "hello", taskItem: task, description: "cheers" }; return item; }); - const selectedTask: MenueItem | undefined = await vscode.window.showQuickPick(taskItems, { placeHolder: localize("select.configuration", "Select a task to configure") }); + const selectedTask: MenueItem | undefined = await window.showQuickPick(taskItems, { placeHolder: localize("select.configuration", "Select a task to configure") }); if (!selectedTask) { throw new Error(); } return [selectedTask.taskItem]; } - public resolveTask(_task: vscode.Task): vscode.Task | undefined { + public resolveTask(_task: Task): Task | undefined { return undefined; } } -export class CppBuildTaskProvider implements vscode.TaskProvider { +export class CppBuildTaskProvider implements TaskProvider { static CppBuildScriptType: string = 'cppbuild'; static CppBuildSourceStr: string = "C/C++"; - private tasks: vscode.Task[] | undefined; + private tasks: Task[] | undefined; constructor() { } - public async provideTasks(): Promise { + public async provideTasks(): Promise { if (this.tasks) { return this.tasks; } @@ -72,8 +76,8 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { } // Resolves a task that has no [`execution`](#Task.execution) set. - public resolveTask(_task: vscode.Task): vscode.Task | undefined { - const execution: vscode.ProcessExecution | vscode.ShellExecution | vscode.CustomExecution | undefined = _task.execution; + public resolveTask(_task: Task): Task | undefined { + const execution: ProcessExecution | ShellExecution | CustomExecution | undefined = _task.execution; if (!execution) { const definition: CppBuildTaskDefinition = _task.definition; return this.getTask(definition.command, false, definition.args ? definition.args : [], definition); @@ -82,12 +86,12 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { } // Generate tasks to build the current file based on the user's detected compilers, the user's compilerPath setting, and the current file's extension. - public async getTasks(appendSourceToName: boolean): Promise { + public async getTasks(appendSourceToName: boolean): Promise { if (this.tasks !== undefined) { return this.tasks; } - const editor: vscode.TextEditor | undefined = vscode.window.activeTextEditor; - let emptyTasks: vscode.Task[] = []; + const editor: TextEditor | undefined = window.activeTextEditor; + const emptyTasks: Task[] = []; if (!editor) { return emptyTasks; } @@ -165,11 +169,11 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { } // Create a build task per compiler path - //this.tasks = []; - let result: vscode.Task[] = []; + // this.tasks = []; + let result: Task[] = []; // Tasks for known compiler paths if (knownCompilerPaths) { - result = knownCompilerPaths.map(compilerPath => this.getTask(compilerPath, appendSourceToName, undefined)); + result = knownCompilerPaths.map(compilerPath => this.getTask(compilerPath, appendSourceToName, undefined)); } // Task for user compiler path setting if (userCompilerPath) { @@ -179,7 +183,7 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { return result; } - private getTask: (compilerPath: string, appendSourceToName: boolean, compilerArgs?: string[], definition?: CppBuildTaskDefinition) => vscode.Task = (compilerPath: string, appendSourceToName: boolean, compilerArgs?: string[], definition?: CppBuildTaskDefinition) => { + private getTask: (compilerPath: string, appendSourceToName: boolean, compilerArgs?: string[], definition?: CppBuildTaskDefinition) => Task = (compilerPath: string, appendSourceToName: boolean, compilerArgs?: string[], definition?: CppBuildTaskDefinition) => { const filePath: string = path.join('${fileDirname}', '${fileBasenameNoExtension}'); const compilerPathBase: string = path.basename(compilerPath); const taskLabel: string = (appendSourceToName ? CppBuildTaskProvider.CppBuildSourceStr + ": " : "") + compilerPathBase + " build active file"; @@ -203,6 +207,7 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { definition = { type: CppBuildTaskProvider.CppBuildScriptType, label: taskName, + description: taskName, command: resolvedcompilerPath, args: args, options: options @@ -210,23 +215,23 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { } const activeClient: Client = ext.getActiveClient(); - const uri: vscode.Uri | undefined = activeClient.RootUri; + const uri: Uri | undefined = activeClient.RootUri; if (!uri) { throw new Error("No client URI found in getBuildTasks()"); } - //const scope: vscode.WorkspaceFolder | undefined = vscode.workspace.getWorkspaceFolder(uri); - const scope: vscode.TaskScope = vscode.TaskScope.Workspace; + // const scope: WorkspaceFolder | undefined = workspace.getWorkspaceFolder(uri); + const scope: TaskScope = TaskScope.Workspace; if (!scope) { throw new Error("No target WorkspaceFolder found in getBuildTasks()"); } - const task: vscode.Task = new vscode.Task(definition, scope, taskLabel, CppBuildTaskProvider.CppBuildSourceStr, - new vscode.CustomExecution(async (): Promise => + const task: Task = new Task(definition, scope, taskLabel, CppBuildTaskProvider.CppBuildSourceStr, + new CustomExecution(async (): Promise => // When the task is executed, this callback will run. Here, we setup for running the task. new CustomBuildTaskTerminal(resolvedcompilerPath, args, options) ), isCl ? '$msCompile' : '$gcc'); - task.group = vscode.TaskGroup.Build; + task.group = TaskGroup.Build; return task; }; @@ -239,12 +244,12 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { rawTasksJson.tasks = new Array(); } // Find or create the task which should be created based on the selected "debug configuration". - let selectedTask: vscode.Task | undefined = rawTasksJson.tasks.find((task: any) => task.label && task.label === taskLabel); + let selectedTask: Task | undefined = rawTasksJson.tasks.find((task: any) => task.label && task.label === taskLabel); if (selectedTask) { return; } - const buildTasks: vscode.Task[] = await this.getTasks(true); + const buildTasks: Task[] = await this.getTasks(true); selectedTask = buildTasks.find(task => task.name === taskLabel); console.assert(selectedTask); if (!selectedTask) { @@ -253,7 +258,7 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { rawTasksJson.version = "2.0.0"; - const selectedTask2: vscode.Task = selectedTask; + const selectedTask2: Task = selectedTask; if (!rawTasksJson.tasks.find((task: any) => task.label === selectedTask2.definition.label)) { const task: any = { ...selectedTask2.definition, @@ -274,16 +279,16 @@ export class CppBuildTaskProvider implements vscode.TaskProvider { } } -class CustomBuildTaskTerminal implements vscode.Pseudoterminal { - private writeEmitter = new vscode.EventEmitter(); - private closeEmitter = new vscode.EventEmitter(); - public get onDidWrite(): vscode.Event { return this.writeEmitter.event; } - public get onDidClose(): vscode.Event { return this.closeEmitter.event; } +class CustomBuildTaskTerminal implements Pseudoterminal { + private writeEmitter = new EventEmitter(); + private closeEmitter = new EventEmitter(); + public get onDidWrite(): Event { return this.writeEmitter.event; } + public get onDidClose(): Event { return this.closeEmitter.event; } constructor(private command: string, private args: string[], private options: cp.ExecOptions | undefined) { } - async open(_initialDimensions: vscode.TerminalDimensions | undefined): Promise { + async open(_initialDimensions: TerminalDimensions | undefined): Promise { telemetry.logLanguageServerEvent("cppBuildTaskStarted"); // At this point we can start using the terminal. this.writeEmitter.fire("Starting build...\r\n"); @@ -337,11 +342,11 @@ class CustomBuildTaskTerminal implements vscode.Pseudoterminal { private get AdditionalEnvironment(): { [key: string]: string | string[] } | undefined { - const editor: vscode.TextEditor | undefined = vscode.window.activeTextEditor; + const editor: TextEditor | undefined = window.activeTextEditor; if (!editor) { return undefined; } - const fileDir: vscode.WorkspaceFolder | undefined = vscode.workspace.getWorkspaceFolder(editor.document.uri); + const fileDir: WorkspaceFolder | undefined = workspace.getWorkspaceFolder(editor.document.uri); if (!fileDir) { return undefined; } @@ -376,11 +381,11 @@ export async function getRawTasksJson(): Promise { } export function getTasksJsonPath(): string | undefined { - const editor: vscode.TextEditor | undefined = vscode.window.activeTextEditor; + const editor: TextEditor | undefined = window.activeTextEditor; if (!editor) { return undefined; } - const folder: vscode.WorkspaceFolder | undefined = vscode.workspace.getWorkspaceFolder(editor.document.uri); + const folder: WorkspaceFolder | undefined = workspace.getWorkspaceFolder(editor.document.uri); if (!folder) { return undefined; } diff --git a/Extension/src/LanguageServer/extension.ts b/Extension/src/LanguageServer/extension.ts index bc7d22f22..37eddfb03 100644 --- a/Extension/src/LanguageServer/extension.ts +++ b/Extension/src/LanguageServer/extension.ts @@ -171,7 +171,8 @@ export function activate(activationEventOccurred: boolean): void { return; } - taskProvider = vscode.tasks.registerTaskProvider(CppBuildTaskProvider.CppBuildScriptType, new QuickPickCppBuildTaskProvider(cppBuildTaskProvider)); + // taskProvider = vscode.tasks.registerTaskProvider(CppBuildTaskProvider.CppBuildScriptType, new QuickPickCppBuildTaskProvider(cppBuildTaskProvider)); + taskProvider = vscode.tasks.registerTaskProvider(CppBuildTaskProvider.CppBuildScriptType, cppBuildTaskProvider); vscode.tasks.onDidStartTask(event => { if (event.execution.task.source === CppBuildTaskProvider.CppBuildSourceStr) { From fae08d0973d495b3c84891174ecfef6549b9008e Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Tue, 11 Aug 2020 15:40:02 -0400 Subject: [PATCH 41/55] Stable, Clean, Before API proposal --- .../LanguageServer/cppBuildTaskProvider.ts | 49 ++++--------------- Extension/src/LanguageServer/extension.ts | 3 +- 2 files changed, 11 insertions(+), 41 deletions(-) diff --git a/Extension/src/LanguageServer/cppBuildTaskProvider.ts b/Extension/src/LanguageServer/cppBuildTaskProvider.ts index 1897c2e08..b619e2d3b 100644 --- a/Extension/src/LanguageServer/cppBuildTaskProvider.ts +++ b/Extension/src/LanguageServer/cppBuildTaskProvider.ts @@ -5,7 +5,7 @@ import * as path from 'path'; import { TaskDefinition, Task, TaskGroup, WorkspaceFolder, ShellExecution, Uri, workspace, - TaskProvider, TaskScope, QuickPickItem, CustomExecution, ProcessExecution, TextEditor, Pseudoterminal, EventEmitter, Event, TerminalDimensions, window + TaskProvider, TaskScope, CustomExecution, ProcessExecution, TextEditor, Pseudoterminal, EventEmitter, Event, TerminalDimensions, window } from 'vscode'; import * as os from 'os'; import * as util from '../common'; @@ -30,37 +30,6 @@ export interface CppBuildTaskDefinition extends TaskDefinition { options: cp.ExecOptions | undefined; } -export class QuickPickCppBuildTaskProvider implements TaskProvider { - private underlyingTaskProvider: TaskProvider; - - public constructor(taskProvider: CppBuildTaskProvider) { - this.underlyingTaskProvider = taskProvider; - } - - public async provideTasks(): Promise { - let tasks: Task[] | undefined | null = this.underlyingTaskProvider.provideTasks ? - await this.underlyingTaskProvider.provideTasks() : undefined; - if (!tasks) { - tasks = []; - } - interface MenueItem extends QuickPickItem { - taskItem: Task; - } - const taskItems: MenueItem[] = tasks.map(task => { - const item: MenueItem = { label: "hello", taskItem: task, description: "cheers" }; - return item; - }); - const selectedTask: MenueItem | undefined = await window.showQuickPick(taskItems, { placeHolder: localize("select.configuration", "Select a task to configure") }); - if (!selectedTask) { - throw new Error(); - } - return [selectedTask.taskItem]; - } - - public resolveTask(_task: Task): Task | undefined { - return undefined; - } -} export class CppBuildTaskProvider implements TaskProvider { static CppBuildScriptType: string = 'cppbuild'; static CppBuildSourceStr: string = "C/C++"; @@ -151,7 +120,7 @@ export class CppBuildTaskProvider implements TaskProvider { // Get known compiler paths. Do not include the known compiler path that is the same as user compiler path. // Filter them based on the file type to get a reduced list appropriate for the active file. - let knownCompilerPaths: string[] | undefined; + const knownCompilerPathsSet: Set = new Set(); let knownCompilers: configs.KnownCompiler[] | undefined = await activeClient.getKnownCompilers(); if (knownCompilers) { knownCompilers = knownCompilers.filter(info => @@ -159,9 +128,12 @@ export class CppBuildTaskProvider implements TaskProvider { userCompilerPathAndArgs && (path.basename(info.path) !== userCompilerPathAndArgs.compilerName) && (!isWindows || !info.path.startsWith("/"))); // TODO: Add WSL compiler support. - knownCompilerPaths = knownCompilers.map(info => info.path); + knownCompilers.map(info => { + knownCompilerPathsSet.add(info.path); + }); } - + const knownCompilerPaths: string[] | undefined = knownCompilerPathsSet.size ? + Array.from(knownCompilerPathsSet) : undefined; if (!knownCompilerPaths && !userCompilerPath) { // Don't prompt a message yet until we can make a data-based decision. telemetry.logLanguageServerEvent('noCompilerFound'); @@ -169,7 +141,6 @@ export class CppBuildTaskProvider implements TaskProvider { } // Create a build task per compiler path - // this.tasks = []; let result: Task[] = []; // Tasks for known compiler paths if (knownCompilerPaths) { @@ -219,12 +190,11 @@ export class CppBuildTaskProvider implements TaskProvider { if (!uri) { throw new Error("No client URI found in getBuildTasks()"); } - // const scope: WorkspaceFolder | undefined = workspace.getWorkspaceFolder(uri); - const scope: TaskScope = TaskScope.Workspace; - if (!scope) { + if (!workspace.getWorkspaceFolder(uri)) { throw new Error("No target WorkspaceFolder found in getBuildTasks()"); } + const scope: TaskScope = TaskScope.Workspace; const task: Task = new Task(definition, scope, taskLabel, CppBuildTaskProvider.CppBuildSourceStr, new CustomExecution(async (): Promise => // When the task is executed, this callback will run. Here, we setup for running the task. @@ -348,6 +318,7 @@ class CustomBuildTaskTerminal implements Pseudoterminal { } const fileDir: WorkspaceFolder | undefined = workspace.getWorkspaceFolder(editor.document.uri); if (!fileDir) { + window.showErrorMessage('This command is not yet available for single-file mode.'); return undefined; } const file: string = editor.document.fileName; diff --git a/Extension/src/LanguageServer/extension.ts b/Extension/src/LanguageServer/extension.ts index 37eddfb03..5e90b367e 100644 --- a/Extension/src/LanguageServer/extension.ts +++ b/Extension/src/LanguageServer/extension.ts @@ -28,7 +28,7 @@ import * as rd from 'readline'; import * as yauzl from 'yauzl'; import { Readable, Writable } from 'stream'; import * as nls from 'vscode-nls'; -import { CppBuildTaskProvider, QuickPickCppBuildTaskProvider } from './cppBuildTaskProvider'; +import { CppBuildTaskProvider } from './cppBuildTaskProvider'; nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })(); const localize: nls.LocalizeFunc = nls.loadMessageBundle(); @@ -171,7 +171,6 @@ export function activate(activationEventOccurred: boolean): void { return; } - // taskProvider = vscode.tasks.registerTaskProvider(CppBuildTaskProvider.CppBuildScriptType, new QuickPickCppBuildTaskProvider(cppBuildTaskProvider)); taskProvider = vscode.tasks.registerTaskProvider(CppBuildTaskProvider.CppBuildScriptType, cppBuildTaskProvider); vscode.tasks.onDidStartTask(event => { From 4b940c5e4ee9eb6dc589cb5c905d03ad7b603b75 Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Mon, 17 Aug 2020 22:44:47 -0400 Subject: [PATCH 42/55] adding details to the tasks menue --- Extension/package.json | 1 + .../LanguageServer/cppBuildTaskProvider.ts | 7 +- Extension/src/vscode.proposed.d.ts | 2051 +++++++++++++++++ 3 files changed, 2057 insertions(+), 2 deletions(-) create mode 100644 Extension/src/vscode.proposed.d.ts diff --git a/Extension/package.json b/Extension/package.json index 6de7d1449..5759f6167 100644 --- a/Extension/package.json +++ b/Extension/package.json @@ -7,6 +7,7 @@ "preview": true, "icon": "LanguageCCPP_color_128x.png", "readme": "README.md", + "enableProposedApi": true, "author": { "name": "Microsoft Corporation" }, diff --git a/Extension/src/LanguageServer/cppBuildTaskProvider.ts b/Extension/src/LanguageServer/cppBuildTaskProvider.ts index b619e2d3b..e15fd8832 100644 --- a/Extension/src/LanguageServer/cppBuildTaskProvider.ts +++ b/Extension/src/LanguageServer/cppBuildTaskProvider.ts @@ -4,7 +4,7 @@ * ------------------------------------------------------------------------------------------ */ import * as path from 'path'; import { - TaskDefinition, Task, TaskGroup, WorkspaceFolder, ShellExecution, Uri, workspace, + TaskDefinition, Task2 as Task, TaskGroup, WorkspaceFolder, ShellExecution, Uri, workspace, TaskProvider, TaskScope, CustomExecution, ProcessExecution, TextEditor, Pseudoterminal, EventEmitter, Event, TerminalDimensions, window } from 'vscode'; import * as os from 'os'; @@ -49,7 +49,9 @@ export class CppBuildTaskProvider implements TaskProvider { const execution: ProcessExecution | ShellExecution | CustomExecution | undefined = _task.execution; if (!execution) { const definition: CppBuildTaskDefinition = _task.definition; - return this.getTask(definition.command, false, definition.args ? definition.args : [], definition); + _task = this.getTask(definition.command, false, definition.args ? definition.args : [], definition); + _task.detail = "Existing task defined in tasks.json."; + return _task; } return undefined; } @@ -202,6 +204,7 @@ export class CppBuildTaskProvider implements TaskProvider { ), isCl ? '$msCompile' : '$gcc'); task.group = TaskGroup.Build; + task.detail = "compiler: " + resolvedcompilerPath; return task; }; diff --git a/Extension/src/vscode.proposed.d.ts b/Extension/src/vscode.proposed.d.ts new file mode 100644 index 000000000..ad6ba64e6 --- /dev/null +++ b/Extension/src/vscode.proposed.d.ts @@ -0,0 +1,2051 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * This is the place for API experiments and proposals. + * These API are NOT stable and subject to change. They are only available in the Insiders + * distribution and CANNOT be used in published extensions. + * + * To test these API in local environment: + * - Use Insiders release of VS Code. + * - Add `"enableProposedApi": true` to your package.json. + * - Copy this file to your project. + */ + +declare module 'vscode' { + + // #region auth provider: https://github.com/microsoft/vscode/issues/88309 + + /** + * An [event](#Event) which fires when an [AuthenticationProvider](#AuthenticationProvider) is added or removed. + */ + export interface AuthenticationProvidersChangeEvent { + /** + * The ids of the [authenticationProvider](#AuthenticationProvider)s that have been added. + */ + readonly added: ReadonlyArray; + + /** + * The ids of the [authenticationProvider](#AuthenticationProvider)s that have been removed. + */ + readonly removed: ReadonlyArray; + } + + /** + * An [event](#Event) which fires when an [AuthenticationSession](#AuthenticationSession) is added, removed, or changed. + */ + export interface AuthenticationProviderAuthenticationSessionsChangeEvent { + /** + * The ids of the [AuthenticationSession](#AuthenticationSession)s that have been added. + */ + readonly added: ReadonlyArray; + + /** + * The ids of the [AuthenticationSession](#AuthenticationSession)s that have been removed. + */ + readonly removed: ReadonlyArray; + + /** + * The ids of the [AuthenticationSession](#AuthenticationSession)s that have been changed. + */ + readonly changed: ReadonlyArray; + } + + /** + * **WARNING** When writing an AuthenticationProvider, `id` should be treated as part of your extension's + * API, changing it is a breaking change for all extensions relying on the provider. The id is + * treated case-sensitively. + */ + export interface AuthenticationProvider { + /** + * Used as an identifier for extensions trying to work with a particular + * provider: 'microsoft', 'github', etc. id must be unique, registering + * another provider with the same id will fail. + */ + readonly id: string; + + /** + * The human-readable name of the provider. + */ + readonly label: string; + + /** + * Whether it is possible to be signed into multiple accounts at once with this provider + */ + readonly supportsMultipleAccounts: boolean; + + /** + * An [event](#Event) which fires when the array of sessions has changed, or data + * within a session has changed. + */ + readonly onDidChangeSessions: Event; + + /** + * Returns an array of current sessions. + */ + getSessions(): Thenable>; + + /** + * Prompts a user to login. + */ + login(scopes: string[]): Thenable; + + /** + * Removes the session corresponding to session id. + * @param sessionId The session id to log out of + */ + logout(sessionId: string): Thenable; + } + + export namespace authentication { + /** + * Register an authentication provider. + * + * There can only be one provider per id and an error is being thrown when an id + * has already been used by another provider. + * + * @param provider The authentication provider provider. + * @return A [disposable](#Disposable) that unregisters this provider when being disposed. + */ + export function registerAuthenticationProvider(provider: AuthenticationProvider): Disposable; + + /** + * Fires with the provider id that was registered or unregistered. + */ + export const onDidChangeAuthenticationProviders: Event; + + /** + * @deprecated + * The ids of the currently registered authentication providers. + * @returns An array of the ids of authentication providers that are currently registered. + */ + export function getProviderIds(): Thenable>; + + /** + * @deprecated + * An array of the ids of authentication providers that are currently registered. + */ + export const providerIds: ReadonlyArray; + + /** + * An array of the information of authentication providers that are currently registered. + */ + export const providers: ReadonlyArray; + + /** + * @deprecated + * Logout of a specific session. + * @param providerId The id of the provider to use + * @param sessionId The session id to remove + * provider + */ + export function logout(providerId: string, sessionId: string): Thenable; + } + + //#endregion + + //#region @alexdima - resolvers + + export interface RemoteAuthorityResolverContext { + resolveAttempt: number; + } + + export class ResolvedAuthority { + readonly host: string; + readonly port: number; + + constructor(host: string, port: number); + } + + export interface ResolvedOptions { + extensionHostEnv?: { [key: string]: string | null; }; + } + + export interface TunnelOptions { + remoteAddress: { port: number, host: string; }; + // The desired local port. If this port can't be used, then another will be chosen. + localAddressPort?: number; + label?: string; + } + + export interface TunnelDescription { + remoteAddress: { port: number, host: string; }; + //The complete local address(ex. localhost:1234) + localAddress: { port: number, host: string; } | string; + } + + export interface Tunnel extends TunnelDescription { + // Implementers of Tunnel should fire onDidDispose when dispose is called. + onDidDispose: Event; + dispose(): void; + } + + /** + * Used as part of the ResolverResult if the extension has any candidate, + * published, or forwarded ports. + */ + export interface TunnelInformation { + /** + * Tunnels that are detected by the extension. The remotePort is used for display purposes. + * The localAddress should be the complete local address (ex. localhost:1234) for connecting to the port. Tunnels provided through + * detected are read-only from the forwarded ports UI. + */ + environmentTunnels?: TunnelDescription[]; + + } + + export type ResolverResult = ResolvedAuthority & ResolvedOptions & TunnelInformation; + + export class RemoteAuthorityResolverError extends Error { + static NotAvailable(message?: string, handled?: boolean): RemoteAuthorityResolverError; + static TemporarilyNotAvailable(message?: string): RemoteAuthorityResolverError; + + constructor(message?: string); + } + + export interface RemoteAuthorityResolver { + resolve(authority: string, context: RemoteAuthorityResolverContext): ResolverResult | Thenable; + /** + * Can be optionally implemented if the extension can forward ports better than the core. + * When not implemented, the core will use its default forwarding logic. + * When implemented, the core will use this to forward ports. + */ + tunnelFactory?: (tunnelOptions: TunnelOptions) => Thenable | undefined; + + /** + * Provides filtering for candidate ports. + */ + showCandidatePort?: (host: string, port: number, detail: string) => Thenable; + } + + export namespace workspace { + /** + * Forwards a port. If the current resolver implements RemoteAuthorityResolver:forwardPort then that will be used to make the tunnel. + * By default, openTunnel only support localhost; however, RemoteAuthorityResolver:tunnelFactory can be used to support other ips. + * + * @throws When run in an environment without a remote. + * + * @param tunnelOptions The `localPort` is a suggestion only. If that port is not available another will be chosen. + */ + export function openTunnel(tunnelOptions: TunnelOptions): Thenable; + + /** + * Gets an array of the currently available tunnels. This does not include environment tunnels, only tunnels that have been created by the user. + * Note that these are of type TunnelDescription and cannot be disposed. + */ + export let tunnels: Thenable; + + /** + * Fired when the list of tunnels has changed. + */ + export const onDidChangeTunnels: Event; + } + + export interface ResourceLabelFormatter { + scheme: string; + authority?: string; + formatting: ResourceLabelFormatting; + } + + export interface ResourceLabelFormatting { + label: string; // myLabel:/${path} + // For historic reasons we use an or string here. Once we finalize this API we should start using enums instead and adopt it in extensions. + // eslint-disable-next-line vscode-dts-literal-or-types + separator: '/' | '\\' | ''; + tildify?: boolean; + normalizeDriveLetter?: boolean; + workspaceSuffix?: string; + authorityPrefix?: string; + stripPathStartingSeparator?: boolean; + } + + export namespace workspace { + export function registerRemoteAuthorityResolver(authorityPrefix: string, resolver: RemoteAuthorityResolver): Disposable; + export function registerResourceLabelFormatter(formatter: ResourceLabelFormatter): Disposable; + } + + //#endregion + + //#region editor insets: https://github.com/microsoft/vscode/issues/85682 + + export interface WebviewEditorInset { + readonly editor: TextEditor; + readonly line: number; + readonly height: number; + readonly webview: Webview; + readonly onDidDispose: Event; + dispose(): void; + } + + export namespace window { + export function createWebviewTextEditorInset(editor: TextEditor, line: number, height: number, options?: WebviewOptions): WebviewEditorInset; + } + + //#endregion + + //#region read/write in chunks: https://github.com/microsoft/vscode/issues/84515 + + export interface FileSystemProvider { + open?(resource: Uri, options: { create: boolean; }): number | Thenable; + close?(fd: number): void | Thenable; + read?(fd: number, pos: number, data: Uint8Array, offset: number, length: number): number | Thenable; + write?(fd: number, pos: number, data: Uint8Array, offset: number, length: number): number | Thenable; + } + + //#endregion + + //#region TextSearchProvider: https://github.com/microsoft/vscode/issues/59921 + + /** + * The parameters of a query for text search. + */ + export interface TextSearchQuery { + /** + * The text pattern to search for. + */ + pattern: string; + + /** + * Whether or not `pattern` should match multiple lines of text. + */ + isMultiline?: boolean; + + /** + * Whether or not `pattern` should be interpreted as a regular expression. + */ + isRegExp?: boolean; + + /** + * Whether or not the search should be case-sensitive. + */ + isCaseSensitive?: boolean; + + /** + * Whether or not to search for whole word matches only. + */ + isWordMatch?: boolean; + } + + /** + * A file glob pattern to match file paths against. + * TODO@roblourens merge this with the GlobPattern docs/definition in vscode.d.ts. + * @see [GlobPattern](#GlobPattern) + */ + export type GlobString = string; + + /** + * Options common to file and text search + */ + export interface SearchOptions { + /** + * The root folder to search within. + */ + folder: Uri; + + /** + * Files that match an `includes` glob pattern should be included in the search. + */ + includes: GlobString[]; + + /** + * Files that match an `excludes` glob pattern should be excluded from the search. + */ + excludes: GlobString[]; + + /** + * Whether external files that exclude files, like .gitignore, should be respected. + * See the vscode setting `"search.useIgnoreFiles"`. + */ + useIgnoreFiles: boolean; + + /** + * Whether symlinks should be followed while searching. + * See the vscode setting `"search.followSymlinks"`. + */ + followSymlinks: boolean; + + /** + * Whether global files that exclude files, like .gitignore, should be respected. + * See the vscode setting `"search.useGlobalIgnoreFiles"`. + */ + useGlobalIgnoreFiles: boolean; + } + + /** + * Options to specify the size of the result text preview. + * These options don't affect the size of the match itself, just the amount of preview text. + */ + export interface TextSearchPreviewOptions { + /** + * The maximum number of lines in the preview. + * Only search providers that support multiline search will ever return more than one line in the match. + */ + matchLines: number; + + /** + * The maximum number of characters included per line. + */ + charsPerLine: number; + } + + /** + * Options that apply to text search. + */ + export interface TextSearchOptions extends SearchOptions { + /** + * The maximum number of results to be returned. + */ + maxResults: number; + + /** + * Options to specify the size of the result text preview. + */ + previewOptions?: TextSearchPreviewOptions; + + /** + * Exclude files larger than `maxFileSize` in bytes. + */ + maxFileSize?: number; + + /** + * Interpret files using this encoding. + * See the vscode setting `"files.encoding"` + */ + encoding?: string; + + /** + * Number of lines of context to include before each match. + */ + beforeContext?: number; + + /** + * Number of lines of context to include after each match. + */ + afterContext?: number; + } + + /** + * Information collected when text search is complete. + */ + export interface TextSearchComplete { + /** + * Whether the search hit the limit on the maximum number of search results. + * `maxResults` on [`TextSearchOptions`](#TextSearchOptions) specifies the max number of results. + * - If exactly that number of matches exist, this should be false. + * - If `maxResults` matches are returned and more exist, this should be true. + * - If search hits an internal limit which is less than `maxResults`, this should be true. + */ + limitHit?: boolean; + } + + /** + * A preview of the text result. + */ + export interface TextSearchMatchPreview { + /** + * The matching lines of text, or a portion of the matching line that contains the match. + */ + text: string; + + /** + * The Range within `text` corresponding to the text of the match. + * The number of matches must match the TextSearchMatch's range property. + */ + matches: Range | Range[]; + } + + /** + * A match from a text search + */ + export interface TextSearchMatch { + /** + * The uri for the matching document. + */ + uri: Uri; + + /** + * The range of the match within the document, or multiple ranges for multiple matches. + */ + ranges: Range | Range[]; + + /** + * A preview of the text match. + */ + preview: TextSearchMatchPreview; + } + + /** + * A line of context surrounding a TextSearchMatch. + */ + export interface TextSearchContext { + /** + * The uri for the matching document. + */ + uri: Uri; + + /** + * One line of text. + * previewOptions.charsPerLine applies to this + */ + text: string; + + /** + * The line number of this line of context. + */ + lineNumber: number; + } + + export type TextSearchResult = TextSearchMatch | TextSearchContext; + + /** + * A TextSearchProvider provides search results for text results inside files in the workspace. + */ + export interface TextSearchProvider { + /** + * Provide results that match the given text pattern. + * @param query The parameters for this query. + * @param options A set of options to consider while searching. + * @param progress A progress callback that must be invoked for all results. + * @param token A cancellation token. + */ + provideTextSearchResults(query: TextSearchQuery, options: TextSearchOptions, progress: Progress, token: CancellationToken): ProviderResult; + } + + //#endregion + + //#region FileSearchProvider: https://github.com/microsoft/vscode/issues/73524 + + /** + * The parameters of a query for file search. + */ + export interface FileSearchQuery { + /** + * The search pattern to match against file paths. + */ + pattern: string; + } + + /** + * Options that apply to file search. + */ + export interface FileSearchOptions extends SearchOptions { + /** + * The maximum number of results to be returned. + */ + maxResults?: number; + + /** + * A CancellationToken that represents the session for this search query. If the provider chooses to, this object can be used as the key for a cache, + * and searches with the same session object can search the same cache. When the token is cancelled, the session is complete and the cache can be cleared. + */ + session?: CancellationToken; + } + + /** + * A FileSearchProvider provides search results for files in the given folder that match a query string. It can be invoked by quickopen or other extensions. + * + * A FileSearchProvider is the more powerful of two ways to implement file search in VS Code. Use a FileSearchProvider if you wish to search within a folder for + * all files that match the user's query. + * + * The FileSearchProvider will be invoked on every keypress in quickopen. When `workspace.findFiles` is called, it will be invoked with an empty query string, + * and in that case, every file in the folder should be returned. + */ + export interface FileSearchProvider { + /** + * Provide the set of files that match a certain file path pattern. + * @param query The parameters for this query. + * @param options A set of options to consider while searching files. + * @param token A cancellation token. + */ + provideFileSearchResults(query: FileSearchQuery, options: FileSearchOptions, token: CancellationToken): ProviderResult; + } + + export namespace workspace { + /** + * Register a search provider. + * + * Only one provider can be registered per scheme. + * + * @param scheme The provider will be invoked for workspace folders that have this file scheme. + * @param provider The provider. + * @return A [disposable](#Disposable) that unregisters this provider when being disposed. + */ + export function registerFileSearchProvider(scheme: string, provider: FileSearchProvider): Disposable; + + /** + * Register a text search provider. + * + * Only one provider can be registered per scheme. + * + * @param scheme The provider will be invoked for workspace folders that have this file scheme. + * @param provider The provider. + * @return A [disposable](#Disposable) that unregisters this provider when being disposed. + */ + export function registerTextSearchProvider(scheme: string, provider: TextSearchProvider): Disposable; + } + + //#endregion + + //#region findTextInFiles: https://github.com/microsoft/vscode/issues/59924 + + /** + * Options that can be set on a findTextInFiles search. + */ + export interface FindTextInFilesOptions { + /** + * A [glob pattern](#GlobPattern) that defines the files to search for. The glob pattern + * will be matched against the file paths of files relative to their workspace. Use a [relative pattern](#RelativePattern) + * to restrict the search results to a [workspace folder](#WorkspaceFolder). + */ + include?: GlobPattern; + + /** + * A [glob pattern](#GlobPattern) that defines files and folders to exclude. The glob pattern + * will be matched against the file paths of resulting matches relative to their workspace. When `undefined`, default excludes will + * apply. + */ + exclude?: GlobPattern; + + /** + * Whether to use the default and user-configured excludes. Defaults to true. + */ + useDefaultExcludes?: boolean; + + /** + * The maximum number of results to search for + */ + maxResults?: number; + + /** + * Whether external files that exclude files, like .gitignore, should be respected. + * See the vscode setting `"search.useIgnoreFiles"`. + */ + useIgnoreFiles?: boolean; + + /** + * Whether global files that exclude files, like .gitignore, should be respected. + * See the vscode setting `"search.useGlobalIgnoreFiles"`. + */ + useGlobalIgnoreFiles?: boolean; + + /** + * Whether symlinks should be followed while searching. + * See the vscode setting `"search.followSymlinks"`. + */ + followSymlinks?: boolean; + + /** + * Interpret files using this encoding. + * See the vscode setting `"files.encoding"` + */ + encoding?: string; + + /** + * Options to specify the size of the result text preview. + */ + previewOptions?: TextSearchPreviewOptions; + + /** + * Number of lines of context to include before each match. + */ + beforeContext?: number; + + /** + * Number of lines of context to include after each match. + */ + afterContext?: number; + } + + export namespace workspace { + /** + * Search text in files across all [workspace folders](#workspace.workspaceFolders) in the workspace. + * @param query The query parameters for the search - the search string, whether it's case-sensitive, or a regex, or matches whole words. + * @param callback A callback, called for each result + * @param token A token that can be used to signal cancellation to the underlying search engine. + * @return A thenable that resolves when the search is complete. + */ + export function findTextInFiles(query: TextSearchQuery, callback: (result: TextSearchResult) => void, token?: CancellationToken): Thenable; + + /** + * Search text in files across all [workspace folders](#workspace.workspaceFolders) in the workspace. + * @param query The query parameters for the search - the search string, whether it's case-sensitive, or a regex, or matches whole words. + * @param options An optional set of query options. Include and exclude patterns, maxResults, etc. + * @param callback A callback, called for each result + * @param token A token that can be used to signal cancellation to the underlying search engine. + * @return A thenable that resolves when the search is complete. + */ + export function findTextInFiles(query: TextSearchQuery, options: FindTextInFilesOptions, callback: (result: TextSearchResult) => void, token?: CancellationToken): Thenable; + } + + //#endregion + + //#region diff command: https://github.com/microsoft/vscode/issues/84899 + + /** + * The contiguous set of modified lines in a diff. + */ + export interface LineChange { + readonly originalStartLineNumber: number; + readonly originalEndLineNumber: number; + readonly modifiedStartLineNumber: number; + readonly modifiedEndLineNumber: number; + } + + export namespace commands { + + /** + * Registers a diff information command that can be invoked via a keyboard shortcut, + * a menu item, an action, or directly. + * + * Diff information commands are different from ordinary [commands](#commands.registerCommand) as + * they only execute when there is an active diff editor when the command is called, and the diff + * information has been computed. Also, the command handler of an editor command has access to + * the diff information. + * + * @param command A unique identifier for the command. + * @param callback A command handler function with access to the [diff information](#LineChange). + * @param thisArg The `this` context used when invoking the handler function. + * @return Disposable which unregisters this command on disposal. + */ + export function registerDiffInformationCommand(command: string, callback: (diff: LineChange[], ...args: any[]) => any, thisArg?: any): Disposable; + } + + //#endregion + + //#region file-decorations: https://github.com/microsoft/vscode/issues/54938 + + export class Decoration { + letter?: string; + title?: string; + color?: ThemeColor; + priority?: number; + bubble?: boolean; + } + + export interface DecorationProvider { + onDidChangeDecorations: Event; + provideDecoration(uri: Uri, token: CancellationToken): ProviderResult; + } + + export namespace window { + export function registerDecorationProvider(provider: DecorationProvider): Disposable; + } + + //#endregion + + //#region debug + + export interface DebugSessionOptions { + /** + * Controls whether this session should run without debugging, thus ignoring breakpoints. + * When this property is not specified, the value from the parent session (if there is one) is used. + */ + noDebug?: boolean; + + /** + * Controls if the debug session's parent session is shown in the CALL STACK view even if it has only a single child. + * By default, the debug session will never hide its parent. + * If compact is true, debug sessions with a single child are hidden in the CALL STACK view to make the tree more compact. + */ + compact?: boolean; + } + + /** + * A DebugProtocolBreakpoint is an opaque stand-in type for the [Breakpoint](https://microsoft.github.io/debug-adapter-protocol/specification#Types_Breakpoint) type defined in the Debug Adapter Protocol. + */ + export interface DebugProtocolBreakpoint { + // Properties: see details [here](https://microsoft.github.io/debug-adapter-protocol/specification#Types_Breakpoint). + } + + export interface DebugSession { + getDebugProtocolBreakpoint(breakpoint: Breakpoint): DebugProtocolBreakpoint | undefined; + } + + // deprecated debug API + + export interface DebugConfigurationProvider { + /** + * Deprecated, use DebugAdapterDescriptorFactory.provideDebugAdapter instead. + * @deprecated Use DebugAdapterDescriptorFactory.createDebugAdapterDescriptor instead + */ + debugAdapterExecutable?(folder: WorkspaceFolder | undefined, token?: CancellationToken): ProviderResult; + } + + //#endregion + + //#region LogLevel: https://github.com/microsoft/vscode/issues/85992 + + /** + * @deprecated DO NOT USE, will be removed + */ + export enum LogLevel { + Trace = 1, + Debug = 2, + Info = 3, + Warning = 4, + Error = 5, + Critical = 6, + Off = 7 + } + + export namespace env { + /** + * @deprecated DO NOT USE, will be removed + */ + export const logLevel: LogLevel; + + /** + * @deprecated DO NOT USE, will be removed + */ + export const onDidChangeLogLevel: Event; + } + + //#endregion + + //#region @joaomoreno: SCM validation + + /** + * Represents the validation type of the Source Control input. + */ + export enum SourceControlInputBoxValidationType { + + /** + * Something not allowed by the rules of a language or other means. + */ + Error = 0, + + /** + * Something suspicious but allowed. + */ + Warning = 1, + + /** + * Something to inform about but not a problem. + */ + Information = 2 + } + + export interface SourceControlInputBoxValidation { + + /** + * The validation message to display. + */ + readonly message: string; + + /** + * The validation type. + */ + readonly type: SourceControlInputBoxValidationType; + } + + /** + * Represents the input box in the Source Control viewlet. + */ + export interface SourceControlInputBox { + + /** + * A validation function for the input box. It's possible to change + * the validation provider simply by setting this property to a different function. + */ + validateInput?(value: string, cursorPosition: number): ProviderResult; + } + + //#endregion + + //#region @joaomoreno: SCM selected provider + + export interface SourceControl { + + /** + * Whether the source control is selected. + */ + readonly selected: boolean; + + /** + * An event signaling when the selection state changes. + */ + readonly onDidChangeSelection: Event; + } + + //#endregion + + //#region Terminal data write event https://github.com/microsoft/vscode/issues/78502 + + export interface TerminalDataWriteEvent { + /** + * The [terminal](#Terminal) for which the data was written. + */ + readonly terminal: Terminal; + /** + * The data being written. + */ + readonly data: string; + } + + namespace window { + /** + * An event which fires when the terminal's child pseudo-device is written to (the shell). + * In other words, this provides access to the raw data stream from the process running + * within the terminal, including VT sequences. + */ + export const onDidWriteTerminalData: Event; + } + + //#endregion + + //#region Terminal dimensions property and change event https://github.com/microsoft/vscode/issues/55718 + + /** + * An [event](#Event) which fires when a [Terminal](#Terminal)'s dimensions change. + */ + export interface TerminalDimensionsChangeEvent { + /** + * The [terminal](#Terminal) for which the dimensions have changed. + */ + readonly terminal: Terminal; + /** + * The new value for the [terminal's dimensions](#Terminal.dimensions). + */ + readonly dimensions: TerminalDimensions; + } + + export namespace window { + /** + * An event which fires when the [dimensions](#Terminal.dimensions) of the terminal change. + */ + export const onDidChangeTerminalDimensions: Event; + } + + export interface Terminal { + /** + * The current dimensions of the terminal. This will be `undefined` immediately after the + * terminal is created as the dimensions are not known until shortly after the terminal is + * created. + */ + readonly dimensions: TerminalDimensions | undefined; + } + + //#endregion + + //#region @jrieken -> exclusive document filters + + export interface DocumentFilter { + exclusive?: boolean; + } + + //#endregion + + //#region @alexdima - OnEnter enhancement + export interface OnEnterRule { + /** + * This rule will only execute if the text above the this line matches this regular expression. + */ + oneLineAboveText?: RegExp; + } + //#endregion + + //#region Tree View: https://github.com/microsoft/vscode/issues/61313 + /** + * Label describing the [Tree item](#TreeItem) + */ + export interface TreeItemLabel { + + /** + * A human-readable string describing the [Tree item](#TreeItem). + */ + label: string; + + /** + * Ranges in the label to highlight. A range is defined as a tuple of two number where the + * first is the inclusive start index and the second the exclusive end index + */ + highlights?: [number, number][]; + + } + + // https://github.com/microsoft/vscode/issues/100741 + export interface TreeDataProvider { + resolveTreeItem?(element: T, item: TreeItem2): TreeItem2 | Thenable; + } + + export class TreeItem2 extends TreeItem { + /** + * Label describing this item. When `falsy`, it is derived from [resourceUri](#TreeItem.resourceUri). + */ + label?: string | TreeItemLabel | /* for compilation */ any; + + /** + * Content to be shown when you hover over the tree item. + */ + tooltip?: string | MarkdownString | /* for compilation */ any; + + /** + * @param label Label describing this item + * @param collapsibleState [TreeItemCollapsibleState](#TreeItemCollapsibleState) of the tree item. Default is [TreeItemCollapsibleState.None](#TreeItemCollapsibleState.None) + */ + constructor(label: TreeItemLabel, collapsibleState?: TreeItemCollapsibleState); + } + //#endregion + + //#region CustomExecution: https://github.com/microsoft/vscode/issues/81007 + /** + * A task to execute + */ + export class Task2 extends Task { + detail?: string; + } + + export class CustomExecution2 extends CustomExecution { + /** + * Constructs a CustomExecution task object. The callback will be executed the task is run, at which point the + * extension should return the Pseudoterminal it will "run in". The task should wait to do further execution until + * [Pseudoterminal.open](#Pseudoterminal.open) is called. Task cancellation should be handled using + * [Pseudoterminal.close](#Pseudoterminal.close). When the task is complete fire + * [Pseudoterminal.onDidClose](#Pseudoterminal.onDidClose). + * @param callback The callback that will be called when the task is started by a user. + */ + constructor(callback: (resolvedDefinition: TaskDefinition) => Thenable); + } + //#endregion + + //#region Task presentation group: https://github.com/microsoft/vscode/issues/47265 + export interface TaskPresentationOptions { + /** + * Controls whether the task is executed in a specific terminal group using split panes. + */ + group?: string; + } + //#endregion + + //#region Status bar item with ID and Name: https://github.com/microsoft/vscode/issues/74972 + + export namespace window { + + /** + * Options to configure the status bar item. + */ + export interface StatusBarItemOptions { + + /** + * A unique identifier of the status bar item. The identifier + * is for example used to allow a user to show or hide the + * status bar item in the UI. + */ + id: string; + + /** + * A human readable name of the status bar item. The name is + * for example used as a label in the UI to show or hide the + * status bar item. + */ + name: string; + + /** + * Accessibility information used when screen reader interacts with this status bar item. + */ + accessibilityInformation?: AccessibilityInformation; + + /** + * The alignment of the status bar item. + */ + alignment?: StatusBarAlignment; + + /** + * The priority of the status bar item. Higher value means the item should + * be shown more to the left. + */ + priority?: number; + } + + /** + * Creates a status bar [item](#StatusBarItem). + * + * @param options The options of the item. If not provided, some default values + * will be assumed. For example, the `StatusBarItemOptions.id` will be the id + * of the extension and the `StatusBarItemOptions.name` will be the extension name. + * @return A new status bar item. + */ + export function createStatusBarItem(options?: StatusBarItemOptions): StatusBarItem; + } + + //#endregion + + //#region OnTypeRename: https://github.com/microsoft/vscode/issues/88424 + + /** + * The rename provider interface defines the contract between extensions and + * the live-rename feature. + */ + export interface OnTypeRenameProvider { + /** + * Provide a list of ranges that can be live renamed together. + * + * @param document The document in which the command was invoked. + * @param position The position at which the command was invoked. + * @param token A cancellation token. + * @return A list of ranges that can be live-renamed togehter. The ranges must have + * identical length and contain identical text content. The ranges cannot overlap. + */ + provideOnTypeRenameRanges(document: TextDocument, position: Position, token: CancellationToken): ProviderResult; + } + + namespace languages { + /** + * Register a rename provider that works on type. + * + * Multiple providers can be registered for a language. In that case providers are sorted + * by their [score](#languages.match) and the best-matching provider is used. Failure + * of the selected provider will cause a failure of the whole operation. + * + * @param selector A selector that defines the documents this provider is applicable to. + * @param provider An on type rename provider. + * @param stopPattern Stop on type renaming when input text matches the regular expression. Defaults to `^\s`. + * @return A [disposable](#Disposable) that unregisters this provider when being disposed. + */ + export function registerOnTypeRenameProvider(selector: DocumentSelector, provider: OnTypeRenameProvider, stopPattern?: RegExp): Disposable; + } + + //#endregion + + //#region Custom editor move https://github.com/microsoft/vscode/issues/86146 + + // TODO: Also for custom editor + + export interface CustomTextEditorProvider { + + /** + * Handle when the underlying resource for a custom editor is renamed. + * + * This allows the webview for the editor be preserved throughout the rename. If this method is not implemented, + * VS Code will destory the previous custom editor and create a replacement one. + * + * @param newDocument New text document to use for the custom editor. + * @param existingWebviewPanel Webview panel for the custom editor. + * @param token A cancellation token that indicates the result is no longer needed. + * + * @return Thenable indicating that the webview editor has been moved. + */ + moveCustomTextEditor?(newDocument: TextDocument, existingWebviewPanel: WebviewPanel, token: CancellationToken): Thenable; + } + + //#endregion + + //#region allow QuickPicks to skip sorting: https://github.com/microsoft/vscode/issues/73904 + + export interface QuickPick extends QuickInput { + /** + * An optional flag to sort the final results by index of first query match in label. Defaults to true. + */ + sortByLabel: boolean; + } + + //#endregion + + //#region @rebornix: Notebook + + export enum CellKind { + Markdown = 1, + Code = 2 + } + + export enum CellOutputKind { + Text = 1, + Error = 2, + Rich = 3 + } + + export interface CellStreamOutput { + outputKind: CellOutputKind.Text; + text: string; + } + + export interface CellErrorOutput { + outputKind: CellOutputKind.Error; + /** + * Exception Name + */ + ename: string; + /** + * Exception Value + */ + evalue: string; + /** + * Exception call stack + */ + traceback: string[]; + } + + export interface NotebookCellOutputMetadata { + /** + * Additional attributes of a cell metadata. + */ + custom?: { [key: string]: any }; + } + + export interface CellDisplayOutput { + outputKind: CellOutputKind.Rich; + /** + * { mime_type: value } + * + * Example: + * ```json + * { + * "outputKind": vscode.CellOutputKind.Rich, + * "data": { + * "text/html": [ + * "

Hello

" + * ], + * "text/plain": [ + * "" + * ] + * } + * } + */ + data: { [key: string]: any; }; + + readonly metadata?: NotebookCellOutputMetadata; + } + + export type CellOutput = CellStreamOutput | CellErrorOutput | CellDisplayOutput; + + export enum NotebookCellRunState { + Running = 1, + Idle = 2, + Success = 3, + Error = 4 + } + + export enum NotebookRunState { + Running = 1, + Idle = 2 + } + + export interface NotebookCellMetadata { + /** + * Controls if the content of a cell is editable or not. + */ + editable?: boolean; + + /** + * Controls if the cell is executable. + * This metadata is ignored for markdown cell. + */ + runnable?: boolean; + + /** + * Controls if the cell has a margin to support the breakpoint UI. + * This metadata is ignored for markdown cell. + */ + breakpointMargin?: boolean; + + /** + * Whether the [execution order](#NotebookCellMetadata.executionOrder) indicator will be displayed. + * Defaults to true. + */ + hasExecutionOrder?: boolean; + + /** + * The order in which this cell was executed. + */ + executionOrder?: number; + + /** + * A status message to be shown in the cell's status bar + */ + statusMessage?: string; + + /** + * The cell's current run state + */ + runState?: NotebookCellRunState; + + /** + * If the cell is running, the time at which the cell started running + */ + runStartTime?: number; + + /** + * The total duration of the cell's last run + */ + lastRunDuration?: number; + + /** + * Whether a code cell's editor is collapsed + */ + inputCollapsed?: boolean; + + /** + * Whether a code cell's outputs are collapsed + */ + outputCollapsed?: boolean; + + /** + * Additional attributes of a cell metadata. + */ + custom?: { [key: string]: any }; + } + + export interface NotebookCell { + readonly notebook: NotebookDocument; + readonly uri: Uri; + readonly cellKind: CellKind; + readonly document: TextDocument; + language: string; + outputs: CellOutput[]; + metadata: NotebookCellMetadata; + } + + export interface NotebookDocumentMetadata { + /** + * Controls if users can add or delete cells + * Defaults to true + */ + editable?: boolean; + + /** + * Controls whether the full notebook can be run at once. + * Defaults to true + */ + runnable?: boolean; + + /** + * Default value for [cell editable metadata](#NotebookCellMetadata.editable). + * Defaults to true. + */ + cellEditable?: boolean; + + /** + * Default value for [cell runnable metadata](#NotebookCellMetadata.runnable). + * Defaults to true. + */ + cellRunnable?: boolean; + + /** + * Default value for [cell hasExecutionOrder metadata](#NotebookCellMetadata.hasExecutionOrder). + * Defaults to true. + */ + cellHasExecutionOrder?: boolean; + + displayOrder?: GlobPattern[]; + + /** + * Additional attributes of the document metadata. + */ + custom?: { [key: string]: any }; + + /** + * The document's current run state + */ + runState?: NotebookRunState; + } + + export interface NotebookDocument { + readonly uri: Uri; + readonly fileName: string; + readonly viewType: string; + readonly isDirty: boolean; + readonly isUntitled: boolean; + readonly cells: NotebookCell[]; + languages: string[]; + displayOrder?: GlobPattern[]; + metadata: NotebookDocumentMetadata; + } + + export interface NotebookConcatTextDocument { + uri: Uri; + isClosed: boolean; + dispose(): void; + onDidChange: Event; + version: number; + getText(): string; + getText(range: Range): string; + + offsetAt(position: Position): number; + positionAt(offset: number): Position; + validateRange(range: Range): Range; + validatePosition(position: Position): Position; + + locationAt(positionOrRange: Position | Range): Location; + positionAt(location: Location): Position; + contains(uri: Uri): boolean + } + + export interface NotebookEditorCellEdit { + insert(index: number, content: string | string[], language: string, type: CellKind, outputs: CellOutput[], metadata: NotebookCellMetadata | undefined): void; + delete(index: number): void; + } + + export interface NotebookEditor { + /** + * The document associated with this notebook editor. + */ + readonly document: NotebookDocument; + + /** + * The primary selected cell on this notebook editor. + */ + readonly selection?: NotebookCell; + + /** + * The column in which this editor shows. + */ + viewColumn?: ViewColumn; + + /** + * Whether the panel is active (focused by the user). + */ + readonly active: boolean; + + /** + * Whether the panel is visible. + */ + readonly visible: boolean; + + /** + * Fired when the panel is disposed. + */ + readonly onDidDispose: Event; + + /** + * Active kernel used in the editor + */ + readonly kernel?: NotebookKernel; + + /** + * Fired when the output hosting webview posts a message. + */ + readonly onDidReceiveMessage: Event; + /** + * Post a message to the output hosting webview. + * + * Messages are only delivered if the editor is live. + * + * @param message Body of the message. This must be a string or other json serilizable object. + */ + postMessage(message: any): Thenable; + + /** + * Convert a uri for the local file system to one that can be used inside outputs webview. + */ + asWebviewUri(localResource: Uri): Uri; + + edit(callback: (editBuilder: NotebookEditorCellEdit) => void): Thenable; + } + + export interface NotebookOutputSelector { + mimeTypes?: string[]; + } + + export interface NotebookRenderRequest { + output: CellDisplayOutput; + mimeType: string; + outputId: string; + } + + export interface NotebookOutputRenderer { + /** + * + * @returns HTML fragment. We can probably return `CellOutput` instead of string ? + * + */ + render(document: NotebookDocument, request: NotebookRenderRequest): string; + + /** + * Call before HTML from the renderer is executed, and will be called for + * every editor associated with notebook documents where the renderer + * is or was used. + * + * The communication object will only send and receive messages to the + * render API, retrieved via `acquireNotebookRendererApi`, acquired with + * this specific renderer's ID. + * + * If you need to keep an association between the communication object + * and the document for use in the `render()` method, you can use a WeakMap. + */ + resolveNotebook?(document: NotebookDocument, communication: NotebookCommunication): void; + + readonly preloads?: Uri[]; + } + + export interface NotebookCellsChangeData { + readonly start: number; + readonly deletedCount: number; + readonly deletedItems: NotebookCell[]; + readonly items: NotebookCell[]; + } + + export interface NotebookCellsChangeEvent { + + /** + * The affected document. + */ + readonly document: NotebookDocument; + readonly changes: ReadonlyArray; + } + + export interface NotebookCellMoveEvent { + + /** + * The affected document. + */ + readonly document: NotebookDocument; + readonly index: number; + readonly newIndex: number; + } + + export interface NotebookCellOutputsChangeEvent { + + /** + * The affected document. + */ + readonly document: NotebookDocument; + readonly cells: NotebookCell[]; + } + + export interface NotebookCellLanguageChangeEvent { + + /** + * The affected document. + */ + readonly document: NotebookDocument; + readonly cell: NotebookCell; + readonly language: string; + } + + export interface NotebookCellMetadataChangeEvent { + readonly document: NotebookDocument; + readonly cell: NotebookCell; + } + + export interface NotebookCellData { + readonly cellKind: CellKind; + readonly source: string; + language: string; + outputs: CellOutput[]; + metadata: NotebookCellMetadata; + } + + export interface NotebookData { + readonly cells: NotebookCellData[]; + readonly languages: string[]; + readonly metadata: NotebookDocumentMetadata; + } + + interface NotebookDocumentContentChangeEvent { + + /** + * The document that the edit is for. + */ + readonly document: NotebookDocument; + } + + interface NotebookDocumentEditEvent { + + /** + * The document that the edit is for. + */ + readonly document: NotebookDocument; + + /** + * Undo the edit operation. + * + * This is invoked by VS Code when the user undoes this edit. To implement `undo`, your + * extension should restore the document and editor to the state they were in just before this + * edit was added to VS Code's internal edit stack by `onDidChangeCustomDocument`. + */ + undo(): Thenable | void; + + /** + * Redo the edit operation. + * + * This is invoked by VS Code when the user redoes this edit. To implement `redo`, your + * extension should restore the document and editor to the state they were in just after this + * edit was added to VS Code's internal edit stack by `onDidChangeCustomDocument`. + */ + redo(): Thenable | void; + + /** + * Display name describing the edit. + * + * This will be shown to users in the UI for undo/redo operations. + */ + readonly label?: string; + } + + interface NotebookDocumentBackup { + /** + * Unique identifier for the backup. + * + * This id is passed back to your extension in `openCustomDocument` when opening a notebook editor from a backup. + */ + readonly id: string; + + /** + * Delete the current backup. + * + * This is called by VS Code when it is clear the current backup is no longer needed, such as when a new backup + * is made or when the file is saved. + */ + delete(): void; + } + + interface NotebookDocumentBackupContext { + readonly destination: Uri; + } + + interface NotebookDocumentOpenContext { + readonly backupId?: string; + } + + /** + * Communication object passed to the {@link NotebookContentProvider} and + * {@link NotebookOutputRenderer} to communicate with the webview. + */ + export interface NotebookCommunication { + /** + * ID of the editor this object communicates with. A single notebook + * document can have multiple attached webviews and editors, when the + * notebook is split for instance. The editor ID lets you differentiate + * between them. + */ + readonly editorId: string; + + /** + * Fired when the output hosting webview posts a message. + */ + readonly onDidReceiveMessage: Event; + /** + * Post a message to the output hosting webview. + * + * Messages are only delivered if the editor is live. + * + * @param message Body of the message. This must be a string or other json serilizable object. + */ + postMessage(message: any): Thenable; + + /** + * Convert a uri for the local file system to one that can be used inside outputs webview. + */ + asWebviewUri(localResource: Uri): Uri; + } + + export interface NotebookContentProvider { + /** + * Content providers should always use [file system providers](#FileSystemProvider) to + * resolve the raw content for `uri` as the resouce is not necessarily a file on disk. + */ + openNotebook(uri: Uri, openContext: NotebookDocumentOpenContext): NotebookData | Promise; + resolveNotebook(document: NotebookDocument, webview: NotebookCommunication): Promise; + saveNotebook(document: NotebookDocument, cancellation: CancellationToken): Promise; + saveNotebookAs(targetResource: Uri, document: NotebookDocument, cancellation: CancellationToken): Promise; + readonly onDidChangeNotebook: Event; + backupNotebook(document: NotebookDocument, context: NotebookDocumentBackupContext, cancellation: CancellationToken): Promise; + + kernel?: NotebookKernel; + } + + export interface NotebookKernel { + readonly id?: string; + label: string; + description?: string; + isPreferred?: boolean; + preloads?: Uri[]; + executeCell(document: NotebookDocument, cell: NotebookCell): void; + cancelCellExecution(document: NotebookDocument, cell: NotebookCell): void; + executeAllCells(document: NotebookDocument): void; + cancelAllCellsExecution(document: NotebookDocument): void; + } + + export interface NotebookDocumentFilter { + viewType?: string; + filenamePattern?: GlobPattern; + excludeFileNamePattern?: GlobPattern; + } + + export interface NotebookKernelProvider { + onDidChangeKernels?: Event; + provideKernels(document: NotebookDocument, token: CancellationToken): ProviderResult; + resolveKernel?(kernel: T, document: NotebookDocument, webview: NotebookCommunication, token: CancellationToken): ProviderResult; + } + + export namespace notebook { + export function registerNotebookContentProvider( + notebookType: string, + provider: NotebookContentProvider + ): Disposable; + + export function registerNotebookKernelProvider( + selector: NotebookDocumentFilter, + provider: NotebookKernelProvider + ): Disposable; + + export function registerNotebookKernel( + id: string, + selectors: GlobPattern[], + kernel: NotebookKernel + ): Disposable; + + export function registerNotebookOutputRenderer( + id: string, + outputSelector: NotebookOutputSelector, + renderer: NotebookOutputRenderer + ): Disposable; + + export const onDidOpenNotebookDocument: Event; + export const onDidCloseNotebookDocument: Event; + export const onDidSaveNotebookDocument: Event; + + /** + * All currently known notebook documents. + */ + export const notebookDocuments: ReadonlyArray; + + export let visibleNotebookEditors: NotebookEditor[]; + export const onDidChangeVisibleNotebookEditors: Event; + + export let activeNotebookEditor: NotebookEditor | undefined; + export const onDidChangeActiveNotebookEditor: Event; + export const onDidChangeNotebookCells: Event; + export const onDidChangeCellOutputs: Event; + export const onDidChangeCellLanguage: Event; + export const onDidChangeCellMetadata: Event; + /** + * Create a document that is the concatenation of all notebook cells. By default all code-cells are included + * but a selector can be provided to narrow to down the set of cells. + * + * @param notebook + * @param selector + */ + export function createConcatTextDocument(notebook: NotebookDocument, selector?: DocumentSelector): NotebookConcatTextDocument; + + export const onDidChangeActiveNotebookKernel: Event<{ document: NotebookDocument, kernel: NotebookKernel | undefined }>; + } + + //#endregion + + //#region https://github.com/microsoft/vscode/issues/39441 + + export interface CompletionItem { + /** + * Will be merged into CompletionItem#label + */ + label2?: CompletionItemLabel; + } + + export interface CompletionItemLabel { + /** + * The function or variable. Rendered leftmost. + */ + name: string; + + /** + * The parameters without the return type. Render after `name`. + */ + parameters?: string; + + /** + * The fully qualified name, like package name or file path. Rendered after `signature`. + */ + qualifier?: string; + + /** + * The return-type of a function or type of a property/variable. Rendered rightmost. + */ + type?: string; + } + + //#endregion + + //#region @eamodio - timeline: https://github.com/microsoft/vscode/issues/84297 + + export class TimelineItem { + /** + * A timestamp (in milliseconds since 1 January 1970 00:00:00) for when the timeline item occurred. + */ + timestamp: number; + + /** + * A human-readable string describing the timeline item. + */ + label: string; + + /** + * Optional id for the timeline item. It must be unique across all the timeline items provided by this source. + * + * If not provided, an id is generated using the timeline item's timestamp. + */ + id?: string; + + /** + * The icon path or [ThemeIcon](#ThemeIcon) for the timeline item. + */ + iconPath?: Uri | { light: Uri; dark: Uri; } | ThemeIcon; + + /** + * A human readable string describing less prominent details of the timeline item. + */ + description?: string; + + /** + * The tooltip text when you hover over the timeline item. + */ + detail?: string; + + /** + * The [command](#Command) that should be executed when the timeline item is selected. + */ + command?: Command; + + /** + * Context value of the timeline item. This can be used to contribute specific actions to the item. + * For example, a timeline item is given a context value as `commit`. When contributing actions to `timeline/item/context` + * using `menus` extension point, you can specify context value for key `timelineItem` in `when` expression like `timelineItem == commit`. + * ``` + * "contributes": { + * "menus": { + * "timeline/item/context": [ + * { + * "command": "extension.copyCommitId", + * "when": "timelineItem == commit" + * } + * ] + * } + * } + * ``` + * This will show the `extension.copyCommitId` action only for items where `contextValue` is `commit`. + */ + contextValue?: string; + + /** + * Accessibility information used when screen reader interacts with this timeline item. + */ + accessibilityInformation?: AccessibilityInformation; + + /** + * @param label A human-readable string describing the timeline item + * @param timestamp A timestamp (in milliseconds since 1 January 1970 00:00:00) for when the timeline item occurred + */ + constructor(label: string, timestamp: number); + } + + export interface TimelineChangeEvent { + /** + * The [uri](#Uri) of the resource for which the timeline changed. + */ + uri: Uri; + + /** + * A flag which indicates whether the entire timeline should be reset. + */ + reset?: boolean; + } + + export interface Timeline { + readonly paging?: { + /** + * A provider-defined cursor specifying the starting point of timeline items which are after the ones returned. + * Use `undefined` to signal that there are no more items to be returned. + */ + readonly cursor: string | undefined; + }; + + /** + * An array of [timeline items](#TimelineItem). + */ + readonly items: readonly TimelineItem[]; + } + + export interface TimelineOptions { + /** + * A provider-defined cursor specifying the starting point of the timeline items that should be returned. + */ + cursor?: string; + + /** + * An optional maximum number timeline items or the all timeline items newer (inclusive) than the timestamp or id that should be returned. + * If `undefined` all timeline items should be returned. + */ + limit?: number | { timestamp: number; id?: string; }; + } + + export interface TimelineProvider { + /** + * An optional event to signal that the timeline for a source has changed. + * To signal that the timeline for all resources (uris) has changed, do not pass any argument or pass `undefined`. + */ + onDidChange?: Event; + + /** + * An identifier of the source of the timeline items. This can be used to filter sources. + */ + readonly id: string; + + /** + * A human-readable string describing the source of the timeline items. This can be used as the display label when filtering sources. + */ + readonly label: string; + + /** + * Provide [timeline items](#TimelineItem) for a [Uri](#Uri). + * + * @param uri The [uri](#Uri) of the file to provide the timeline for. + * @param options A set of options to determine how results should be returned. + * @param token A cancellation token. + * @return The [timeline result](#TimelineResult) or a thenable that resolves to such. The lack of a result + * can be signaled by returning `undefined`, `null`, or an empty array. + */ + provideTimeline(uri: Uri, options: TimelineOptions, token: CancellationToken): ProviderResult; + } + + export namespace workspace { + /** + * Register a timeline provider. + * + * Multiple providers can be registered. In that case, providers are asked in + * parallel and the results are merged. A failing provider (rejected promise or exception) will + * not cause a failure of the whole operation. + * + * @param scheme A scheme or schemes that defines which documents this provider is applicable to. Can be `*` to target all documents. + * @param provider A timeline provider. + * @return A [disposable](#Disposable) that unregisters this provider when being disposed. + */ + export function registerTimelineProvider(scheme: string | string[], provider: TimelineProvider): Disposable; + } + + //#endregion + + //#region https://github.com/microsoft/vscode/issues/91555 + + export enum StandardTokenType { + Other = 0, + Comment = 1, + String = 2, + RegEx = 4 + } + + export interface TokenInformation { + type: StandardTokenType; + range: Range; + } + + export namespace languages { + export function getTokenInformationAtPosition(document: TextDocument, position: Position): Promise; + } + + //#endregion + + //#region Support `scmResourceState` in `when` clauses #86180 https://github.com/microsoft/vscode/issues/86180 + + export interface SourceControlResourceState { + /** + * Context value of the resource state. This can be used to contribute resource specific actions. + * For example, if a resource is given a context value as `diffable`. When contributing actions to `scm/resourceState/context` + * using `menus` extension point, you can specify context value for key `scmResourceState` in `when` expressions, like `scmResourceState == diffable`. + * ``` + * "contributes": { + * "menus": { + * "scm/resourceState/context": [ + * { + * "command": "extension.diff", + * "when": "scmResourceState == diffable" + * } + * ] + * } + * } + * ``` + * This will show action `extension.diff` only for resources with `contextValue` is `diffable`. + */ + readonly contextValue?: string; + } + + //#endregion + //#region https://github.com/microsoft/vscode/issues/101857 + + export interface ExtensionContext { + + /** + * The uri of a directory in which the extension can create log files. + * The directory might not exist on disk and creation is up to the extension. However, + * the parent directory is guaranteed to be existent. + * + * @see [`workspace.fs`](#FileSystem) for how to read and write files and folders from + * an uri. + */ + readonly logUri: Uri; + + /** + * The uri of a workspace specific directory in which the extension + * can store private state. The directory might not exist and creation is + * up to the extension. However, the parent directory is guaranteed to be existent. + * The value is `undefined` when no workspace nor folder has been opened. + * + * Use [`workspaceState`](#ExtensionContext.workspaceState) or + * [`globalState`](#ExtensionContext.globalState) to store key value data. + * + * @see [`workspace.fs`](#FileSystem) for how to read and write files and folders from + * an uri. + */ + readonly storageUri: Uri | undefined; + + /** + * The uri of a directory in which the extension can store global state. + * The directory might not exist on disk and creation is + * up to the extension. However, the parent directory is guaranteed to be existent. + * + * Use [`globalState`](#ExtensionContext.globalState) to store key value data. + * + * @see [`workspace.fs`](#FileSystem) for how to read and write files and folders from + * an uri. + */ + readonly globalStorageUri: Uri; + + /** + * @deprecated Use [logUri](#ExtensionContext.logUri) instead. + */ + readonly logPath: string; + /** + * @deprecated Use [storagePath](#ExtensionContent.storageUri) instead. + */ + readonly storagePath: string | undefined; + /** + * @deprecated Use [globalStoragePath](#ExtensionContent.globalStorageUri) instead. + */ + readonly globalStoragePath: string; + } + + //#endregion + + //#region https://github.com/microsoft/vscode/issues/104436 + + export enum ExtensionRuntime { + /** + * The extension is running in a NodeJS extension host. Runtime access to NodeJS APIs is available. + */ + Node = 1, + /** + * The extension is running in a Webworker extension host. Runtime access is limited to Webworker APIs. + */ + Webworker = 2 + } + + export interface ExtensionContext { + readonly extensionRuntime: ExtensionRuntime; + } + + //#endregion + + + //#region https://github.com/microsoft/vscode/issues/102091 + + export interface TextDocument { + + /** + * The [notebook](#NotebookDocument) that contains this document as a notebook cell or `undefined` when + * the document is not contained by a notebook (this should be the more frequent case). + */ + notebook: NotebookDocument | undefined; + } + //#endregion +} \ No newline at end of file From d4c5312569c2469cdfad6ce6e80de6707dfe7f2b Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Wed, 19 Aug 2020 13:41:34 -0400 Subject: [PATCH 43/55] add TODO --- Extension/src/LanguageServer/cppBuildTaskProvider.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Extension/src/LanguageServer/cppBuildTaskProvider.ts b/Extension/src/LanguageServer/cppBuildTaskProvider.ts index e15fd8832..7147a9a8c 100644 --- a/Extension/src/LanguageServer/cppBuildTaskProvider.ts +++ b/Extension/src/LanguageServer/cppBuildTaskProvider.ts @@ -50,7 +50,9 @@ export class CppBuildTaskProvider implements TaskProvider { if (!execution) { const definition: CppBuildTaskDefinition = _task.definition; _task = this.getTask(definition.command, false, definition.args ? definition.args : [], definition); - _task.detail = "Existing task defined in tasks.json."; + // TODO: currently, no tasks are resolved when the quick pick is shown. + // This change will not be effective in VS Code 1.49. + // _task.detail = "Existing task defined in tasks.json."; return _task; } return undefined; From 7e8885ee0e34357c6d6af64bcc781f0a5d6db335 Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Fri, 21 Aug 2020 12:35:00 -0400 Subject: [PATCH 44/55] remove extra ",remove description,merge from local --- Extension/package.json | 4 ---- Extension/src/LanguageServer/cppBuildTaskProvider.ts | 4 +--- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/Extension/package.json b/Extension/package.json index 5759f6167..31883fb87 100644 --- a/Extension/package.json +++ b/Extension/package.json @@ -56,10 +56,6 @@ "type": "string", "description": "%c_cpp.taskDefinitions.name.description%" }, - "description": { - "type": "string", - "description": "description of the task." - }, "command": { "type": "string", "description": "%c_cpp.taskDefinitions.command.description%" diff --git a/Extension/src/LanguageServer/cppBuildTaskProvider.ts b/Extension/src/LanguageServer/cppBuildTaskProvider.ts index 7147a9a8c..612388d66 100644 --- a/Extension/src/LanguageServer/cppBuildTaskProvider.ts +++ b/Extension/src/LanguageServer/cppBuildTaskProvider.ts @@ -24,7 +24,6 @@ export const failedToParseTasksJson: string = localize("failed.to.parse.tasks", export interface CppBuildTaskDefinition extends TaskDefinition { type: string; label: string; // The label appears in tasks.json file. - description: string; command: string; args: string[]; options: cp.ExecOptions | undefined; @@ -182,8 +181,7 @@ export class CppBuildTaskProvider implements TaskProvider { definition = { type: CppBuildTaskProvider.CppBuildScriptType, label: taskName, - description: taskName, - command: resolvedcompilerPath, + command: isCl ? compilerPathBase : compilerPath, args: args, options: options }; From d2d10d43885cf81d92f1cbe7b1ccd783e2c66ffc Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Fri, 21 Aug 2020 15:10:13 -0400 Subject: [PATCH 45/55] remove task rename in this versoin --- Extension/src/LanguageServer/cppBuildTaskProvider.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Extension/src/LanguageServer/cppBuildTaskProvider.ts b/Extension/src/LanguageServer/cppBuildTaskProvider.ts index 612388d66..3e0d43c39 100644 --- a/Extension/src/LanguageServer/cppBuildTaskProvider.ts +++ b/Extension/src/LanguageServer/cppBuildTaskProvider.ts @@ -161,7 +161,9 @@ export class CppBuildTaskProvider implements TaskProvider { const filePath: string = path.join('${fileDirname}', '${fileBasenameNoExtension}'); const compilerPathBase: string = path.basename(compilerPath); const taskLabel: string = (appendSourceToName ? CppBuildTaskProvider.CppBuildSourceStr + ": " : "") + compilerPathBase + " build active file"; - const taskName: string = "Build with " + compilerPathBase + "."; + // TODO: currently, the name of the task in the tasks.json file, and the label shown in quickpick menu are not differentiable. + // This change will not be effective in VS Code 1.49. + // const taskName: string = "Build with " + compilerPathBase + "."; const isCl: boolean = compilerPathBase === "cl.exe"; const isWindows: boolean = os.platform() === 'win32'; const cwd: string = isCl ? "${workspaceFolder}" : path.dirname(compilerPath); @@ -180,7 +182,7 @@ export class CppBuildTaskProvider implements TaskProvider { if (!definition) { definition = { type: CppBuildTaskProvider.CppBuildScriptType, - label: taskName, + label: taskLabel, command: isCl ? compilerPathBase : compilerPath, args: args, options: options From a4841f38ac0c7e63920945af712bbf801e119636 Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Mon, 24 Aug 2020 10:17:00 -0700 Subject: [PATCH 46/55] remove TODOs --- Extension/src/LanguageServer/cppBuildTaskProvider.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Extension/src/LanguageServer/cppBuildTaskProvider.ts b/Extension/src/LanguageServer/cppBuildTaskProvider.ts index 3e0d43c39..b17f91796 100644 --- a/Extension/src/LanguageServer/cppBuildTaskProvider.ts +++ b/Extension/src/LanguageServer/cppBuildTaskProvider.ts @@ -49,9 +49,6 @@ export class CppBuildTaskProvider implements TaskProvider { if (!execution) { const definition: CppBuildTaskDefinition = _task.definition; _task = this.getTask(definition.command, false, definition.args ? definition.args : [], definition); - // TODO: currently, no tasks are resolved when the quick pick is shown. - // This change will not be effective in VS Code 1.49. - // _task.detail = "Existing task defined in tasks.json."; return _task; } return undefined; @@ -161,9 +158,6 @@ export class CppBuildTaskProvider implements TaskProvider { const filePath: string = path.join('${fileDirname}', '${fileBasenameNoExtension}'); const compilerPathBase: string = path.basename(compilerPath); const taskLabel: string = (appendSourceToName ? CppBuildTaskProvider.CppBuildSourceStr + ": " : "") + compilerPathBase + " build active file"; - // TODO: currently, the name of the task in the tasks.json file, and the label shown in quickpick menu are not differentiable. - // This change will not be effective in VS Code 1.49. - // const taskName: string = "Build with " + compilerPathBase + "."; const isCl: boolean = compilerPathBase === "cl.exe"; const isWindows: boolean = os.platform() === 'win32'; const cwd: string = isCl ? "${workspaceFolder}" : path.dirname(compilerPath); From f78ec143d0e9660d2cbd42a72513427375bd2717 Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Mon, 24 Aug 2020 12:19:04 -0700 Subject: [PATCH 47/55] merge the "default" stuff --- .../LanguageServer/cppBuildTaskProvider.ts | 28 +++++++++++++------ 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/Extension/src/LanguageServer/cppBuildTaskProvider.ts b/Extension/src/LanguageServer/cppBuildTaskProvider.ts index b17f91796..7e67c2e9f 100644 --- a/Extension/src/LanguageServer/cppBuildTaskProvider.ts +++ b/Extension/src/LanguageServer/cppBuildTaskProvider.ts @@ -157,7 +157,8 @@ export class CppBuildTaskProvider implements TaskProvider { private getTask: (compilerPath: string, appendSourceToName: boolean, compilerArgs?: string[], definition?: CppBuildTaskDefinition) => Task = (compilerPath: string, appendSourceToName: boolean, compilerArgs?: string[], definition?: CppBuildTaskDefinition) => { const filePath: string = path.join('${fileDirname}', '${fileBasenameNoExtension}'); const compilerPathBase: string = path.basename(compilerPath); - const taskLabel: string = (appendSourceToName ? CppBuildTaskProvider.CppBuildSourceStr + ": " : "") + compilerPathBase + " build active file"; + const taskLabel: string = ((appendSourceToName && !compilerPathBase.startsWith(CppBuildTaskProvider.CppBuildSourceStr)) ? + CppBuildTaskProvider.CppBuildSourceStr + ": " : "") + compilerPathBase + " build active file"; const isCl: boolean = compilerPathBase === "cl.exe"; const isWindows: boolean = os.platform() === 'win32'; const cwd: string = isCl ? "${workspaceFolder}" : path.dirname(compilerPath); @@ -227,14 +228,24 @@ export class CppBuildTaskProvider implements TaskProvider { rawTasksJson.version = "2.0.0"; - const selectedTask2: Task = selectedTask; - if (!rawTasksJson.tasks.find((task: any) => task.label === selectedTask2.definition.label)) { - const task: any = { - ...selectedTask2.definition, - problemMatcher: selectedTask2.problemMatchers, - group: { kind: "build", "isDefault": true } + // Modify the current default task + rawTasksJson.tasks.forEach((task: any) => { + if (task.label === selectedTask?.definition.label) { + task.group = { kind: "build", "isDefault": true }; + } + else if (task.group.kind && task.group.kind === "build" && task.group.isDefault && task.group.isDefault === true) { + task.group = "build"; + } + }); + + if (!rawTasksJson.tasks.find((task: any) => task.label === selectedTask?.definition.label)) { + const newTask: any = { + ...selectedTask.definition, + problemMatcher: selectedTask.problemMatchers, + group: { kind: "build", "isDefault": true }, + detail: "Generated task by Debugger" }; - rawTasksJson.tasks.push(task); + rawTasksJson.tasks.push(newTask); } // TODO: It's dangerous to overwrite this file. We could be wiping out comments. @@ -310,7 +321,6 @@ class CustomBuildTaskTerminal implements Pseudoterminal { } private get AdditionalEnvironment(): { [key: string]: string | string[] } | undefined { - const editor: TextEditor | undefined = window.activeTextEditor; if (!editor) { return undefined; From 3406b5f871bbe0e1e87feaaf65d23d725217e7cb Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Mon, 24 Aug 2020 12:59:06 -0700 Subject: [PATCH 48/55] remove some parts of proposals --- Extension/src/vscode.proposed.d.ts | 276 ----------------------------- 1 file changed, 276 deletions(-) diff --git a/Extension/src/vscode.proposed.d.ts b/Extension/src/vscode.proposed.d.ts index ad6ba64e6..d49507f51 100644 --- a/Extension/src/vscode.proposed.d.ts +++ b/Extension/src/vscode.proposed.d.ts @@ -18,21 +18,6 @@ declare module 'vscode' { // #region auth provider: https://github.com/microsoft/vscode/issues/88309 - /** - * An [event](#Event) which fires when an [AuthenticationProvider](#AuthenticationProvider) is added or removed. - */ - export interface AuthenticationProvidersChangeEvent { - /** - * The ids of the [authenticationProvider](#AuthenticationProvider)s that have been added. - */ - readonly added: ReadonlyArray; - - /** - * The ids of the [authenticationProvider](#AuthenticationProvider)s that have been removed. - */ - readonly removed: ReadonlyArray; - } - /** * An [event](#Event) which fires when an [AuthenticationSession](#AuthenticationSession) is added, removed, or changed. */ @@ -53,96 +38,7 @@ declare module 'vscode' { readonly changed: ReadonlyArray; } - /** - * **WARNING** When writing an AuthenticationProvider, `id` should be treated as part of your extension's - * API, changing it is a breaking change for all extensions relying on the provider. The id is - * treated case-sensitively. - */ - export interface AuthenticationProvider { - /** - * Used as an identifier for extensions trying to work with a particular - * provider: 'microsoft', 'github', etc. id must be unique, registering - * another provider with the same id will fail. - */ - readonly id: string; - - /** - * The human-readable name of the provider. - */ - readonly label: string; - - /** - * Whether it is possible to be signed into multiple accounts at once with this provider - */ - readonly supportsMultipleAccounts: boolean; - - /** - * An [event](#Event) which fires when the array of sessions has changed, or data - * within a session has changed. - */ - readonly onDidChangeSessions: Event; - - /** - * Returns an array of current sessions. - */ - getSessions(): Thenable>; - - /** - * Prompts a user to login. - */ - login(scopes: string[]): Thenable; - - /** - * Removes the session corresponding to session id. - * @param sessionId The session id to log out of - */ - logout(sessionId: string): Thenable; - } - - export namespace authentication { - /** - * Register an authentication provider. - * - * There can only be one provider per id and an error is being thrown when an id - * has already been used by another provider. - * - * @param provider The authentication provider provider. - * @return A [disposable](#Disposable) that unregisters this provider when being disposed. - */ - export function registerAuthenticationProvider(provider: AuthenticationProvider): Disposable; - - /** - * Fires with the provider id that was registered or unregistered. - */ - export const onDidChangeAuthenticationProviders: Event; - - /** - * @deprecated - * The ids of the currently registered authentication providers. - * @returns An array of the ids of authentication providers that are currently registered. - */ - export function getProviderIds(): Thenable>; - - /** - * @deprecated - * An array of the ids of authentication providers that are currently registered. - */ - export const providerIds: ReadonlyArray; - - /** - * An array of the information of authentication providers that are currently registered. - */ - export const providers: ReadonlyArray; - /** - * @deprecated - * Logout of a specific session. - * @param providerId The id of the provider to use - * @param sessionId The session id to remove - * provider - */ - export function logout(providerId: string, sessionId: string): Thenable; - } //#endregion @@ -1021,54 +917,7 @@ declare module 'vscode' { //#region Status bar item with ID and Name: https://github.com/microsoft/vscode/issues/74972 - export namespace window { - - /** - * Options to configure the status bar item. - */ - export interface StatusBarItemOptions { - - /** - * A unique identifier of the status bar item. The identifier - * is for example used to allow a user to show or hide the - * status bar item in the UI. - */ - id: string; - - /** - * A human readable name of the status bar item. The name is - * for example used as a label in the UI to show or hide the - * status bar item. - */ - name: string; - /** - * Accessibility information used when screen reader interacts with this status bar item. - */ - accessibilityInformation?: AccessibilityInformation; - - /** - * The alignment of the status bar item. - */ - alignment?: StatusBarAlignment; - - /** - * The priority of the status bar item. Higher value means the item should - * be shown more to the left. - */ - priority?: number; - } - - /** - * Creates a status bar [item](#StatusBarItem). - * - * @param options The options of the item. If not provided, some default values - * will be assumed. For example, the `StatusBarItemOptions.id` will be the id - * of the extension and the `StatusBarItemOptions.name` will be the extension name. - * @return A new status bar item. - */ - export function createStatusBarItem(options?: StatusBarItemOptions): StatusBarItem; - } //#endregion @@ -1760,75 +1609,6 @@ declare module 'vscode' { //#region @eamodio - timeline: https://github.com/microsoft/vscode/issues/84297 - export class TimelineItem { - /** - * A timestamp (in milliseconds since 1 January 1970 00:00:00) for when the timeline item occurred. - */ - timestamp: number; - - /** - * A human-readable string describing the timeline item. - */ - label: string; - - /** - * Optional id for the timeline item. It must be unique across all the timeline items provided by this source. - * - * If not provided, an id is generated using the timeline item's timestamp. - */ - id?: string; - - /** - * The icon path or [ThemeIcon](#ThemeIcon) for the timeline item. - */ - iconPath?: Uri | { light: Uri; dark: Uri; } | ThemeIcon; - - /** - * A human readable string describing less prominent details of the timeline item. - */ - description?: string; - - /** - * The tooltip text when you hover over the timeline item. - */ - detail?: string; - - /** - * The [command](#Command) that should be executed when the timeline item is selected. - */ - command?: Command; - - /** - * Context value of the timeline item. This can be used to contribute specific actions to the item. - * For example, a timeline item is given a context value as `commit`. When contributing actions to `timeline/item/context` - * using `menus` extension point, you can specify context value for key `timelineItem` in `when` expression like `timelineItem == commit`. - * ``` - * "contributes": { - * "menus": { - * "timeline/item/context": [ - * { - * "command": "extension.copyCommitId", - * "when": "timelineItem == commit" - * } - * ] - * } - * } - * ``` - * This will show the `extension.copyCommitId` action only for items where `contextValue` is `commit`. - */ - contextValue?: string; - - /** - * Accessibility information used when screen reader interacts with this timeline item. - */ - accessibilityInformation?: AccessibilityInformation; - - /** - * @param label A human-readable string describing the timeline item - * @param timestamp A timestamp (in milliseconds since 1 January 1970 00:00:00) for when the timeline item occurred - */ - constructor(label: string, timestamp: number); - } export interface TimelineChangeEvent { /** @@ -1842,20 +1622,6 @@ declare module 'vscode' { reset?: boolean; } - export interface Timeline { - readonly paging?: { - /** - * A provider-defined cursor specifying the starting point of timeline items which are after the ones returned. - * Use `undefined` to signal that there are no more items to be returned. - */ - readonly cursor: string | undefined; - }; - - /** - * An array of [timeline items](#TimelineItem). - */ - readonly items: readonly TimelineItem[]; - } export interface TimelineOptions { /** @@ -1870,49 +1636,7 @@ declare module 'vscode' { limit?: number | { timestamp: number; id?: string; }; } - export interface TimelineProvider { - /** - * An optional event to signal that the timeline for a source has changed. - * To signal that the timeline for all resources (uris) has changed, do not pass any argument or pass `undefined`. - */ - onDidChange?: Event; - - /** - * An identifier of the source of the timeline items. This can be used to filter sources. - */ - readonly id: string; - - /** - * A human-readable string describing the source of the timeline items. This can be used as the display label when filtering sources. - */ - readonly label: string; - /** - * Provide [timeline items](#TimelineItem) for a [Uri](#Uri). - * - * @param uri The [uri](#Uri) of the file to provide the timeline for. - * @param options A set of options to determine how results should be returned. - * @param token A cancellation token. - * @return The [timeline result](#TimelineResult) or a thenable that resolves to such. The lack of a result - * can be signaled by returning `undefined`, `null`, or an empty array. - */ - provideTimeline(uri: Uri, options: TimelineOptions, token: CancellationToken): ProviderResult; - } - - export namespace workspace { - /** - * Register a timeline provider. - * - * Multiple providers can be registered. In that case, providers are asked in - * parallel and the results are merged. A failing provider (rejected promise or exception) will - * not cause a failure of the whole operation. - * - * @param scheme A scheme or schemes that defines which documents this provider is applicable to. Can be `*` to target all documents. - * @param provider A timeline provider. - * @return A [disposable](#Disposable) that unregisters this provider when being disposed. - */ - export function registerTimelineProvider(scheme: string | string[], provider: TimelineProvider): Disposable; - } //#endregion From 4552894fd683ea144c929e51b34cf415eda6a1ab Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Mon, 24 Aug 2020 13:04:45 -0700 Subject: [PATCH 49/55] fix linter errors --- Extension/src/LanguageServer/cppBuildTaskProvider.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Extension/src/LanguageServer/cppBuildTaskProvider.ts b/Extension/src/LanguageServer/cppBuildTaskProvider.ts index 7e67c2e9f..6e6aff0f1 100644 --- a/Extension/src/LanguageServer/cppBuildTaskProvider.ts +++ b/Extension/src/LanguageServer/cppBuildTaskProvider.ts @@ -232,8 +232,7 @@ export class CppBuildTaskProvider implements TaskProvider { rawTasksJson.tasks.forEach((task: any) => { if (task.label === selectedTask?.definition.label) { task.group = { kind: "build", "isDefault": true }; - } - else if (task.group.kind && task.group.kind === "build" && task.group.isDefault && task.group.isDefault === true) { + } else if (task.group.kind && task.group.kind === "build" && task.group.isDefault && task.group.isDefault === true) { task.group = "build"; } }); From c9b612e7f50e41305ca09d1d236563adadd1aceb Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Mon, 24 Aug 2020 16:00:56 -0700 Subject: [PATCH 50/55] add import * as which from 'which'; --- Extension/src/LanguageServer/configurations.ts | 1 + Extension/src/LanguageServer/extension.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/Extension/src/LanguageServer/configurations.ts b/Extension/src/LanguageServer/configurations.ts index e8a8687bd..cca6f8722 100644 --- a/Extension/src/LanguageServer/configurations.ts +++ b/Extension/src/LanguageServer/configurations.ts @@ -19,6 +19,7 @@ import escapeStringRegExp = require('escape-string-regexp'); import * as jsonc from 'jsonc-parser'; import * as nls from 'vscode-nls'; import { setTimeout } from 'timers'; +import * as which from 'which'; nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })(); const localize: nls.LocalizeFunc = nls.loadMessageBundle(); diff --git a/Extension/src/LanguageServer/extension.ts b/Extension/src/LanguageServer/extension.ts index 1846ffcd7..86b6b1196 100644 --- a/Extension/src/LanguageServer/extension.ts +++ b/Extension/src/LanguageServer/extension.ts @@ -30,6 +30,7 @@ import { Readable, Writable } from 'stream'; import { ABTestSettings, getABTestSettings } from '../abTesting'; import * as nls from 'vscode-nls'; import { CppBuildTaskProvider } from './cppBuildTaskProvider'; +import * as which from 'which'; nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })(); const localize: nls.LocalizeFunc = nls.loadMessageBundle(); From 3363b14b8adacd5ee0a2e9125ea7237b3efad060 Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Thu, 10 Sep 2020 15:15:55 -0700 Subject: [PATCH 51/55] clean up the code after version 1.0.0 --- Extension/src/Debugger/extension.ts | 7 +- .../LanguageServer/cppBuildTaskProvider.ts | 81 ++++++++------- Extension/src/common.ts | 99 ++----------------- 3 files changed, 51 insertions(+), 136 deletions(-) diff --git a/Extension/src/Debugger/extension.ts b/Extension/src/Debugger/extension.ts index 41a8ed625..fed2812e5 100644 --- a/Extension/src/Debugger/extension.ts +++ b/Extension/src/Debugger/extension.ts @@ -9,7 +9,6 @@ import { AttachPicker, RemoteAttachPicker, AttachItemsProvider } from './attachT import { NativeAttachItemsProviderFactory } from './nativeAttach'; import { QuickPickConfigurationProvider, ConfigurationAssetProviderFactory, CppVsDbgConfigurationProvider, CppDbgConfigurationProvider, ConfigurationSnippetProvider, IConfigurationAssetProvider } from './configurationProvider'; import { CppdbgDebugAdapterDescriptorFactory, CppvsdbgDebugAdapterDescriptorFactory } from './debugAdapterDescriptorFactory'; -import { failedToParseTasksJson } from '../LanguageServer/cppBuildTaskProvider'; import * as util from '../common'; import * as Telemetry from '../telemetry'; import * as nls from 'vscode-nls'; @@ -93,8 +92,8 @@ export function initialize(context: vscode.ExtensionContext): void { await cppBuildTaskProvider.ensureBuildTaskExists(selection.configuration.preLaunchTask); Telemetry.logDebuggerEvent("buildAndDebug", { "success": "false" }); } catch (e) { - if (e && e.message === failedToParseTasksJson) { - vscode.window.showErrorMessage(failedToParseTasksJson); + if (e && e.message === util.failedToParseJson) { + vscode.window.showErrorMessage(util.failedToParseJson); } return Promise.resolve(); } @@ -110,7 +109,7 @@ export function initialize(context: vscode.ExtensionContext): void { // Attempt to use the user's (possibly) modified configuration before using the generated one. try { - await util.ensureDebugConfigExists(selection.configuration.name); + await cppBuildTaskProvider.ensureDebugConfigExists(selection.configuration.name); try { await vscode.debug.startDebugging(folder, selection.configuration.name); Telemetry.logDebuggerEvent("buildAndDebug", { "success": "true" }); diff --git a/Extension/src/LanguageServer/cppBuildTaskProvider.ts b/Extension/src/LanguageServer/cppBuildTaskProvider.ts index 6e6aff0f1..1f4226572 100644 --- a/Extension/src/LanguageServer/cppBuildTaskProvider.ts +++ b/Extension/src/LanguageServer/cppBuildTaskProvider.ts @@ -13,13 +13,8 @@ import * as telemetry from '../telemetry'; import { Client } from './client'; import * as configs from './configurations'; import * as ext from './extension'; -import * as nls from 'vscode-nls'; import * as cp from "child_process"; import { OtherSettings } from './settings'; -import * as jsonc from 'jsonc-parser'; - -const localize: nls.LocalizeFunc = nls.loadMessageBundle(); -export const failedToParseTasksJson: string = localize("failed.to.parse.tasks", "Failed to parse tasks.json, possibly due to comments or trailing commas."); export interface CppBuildTaskDefinition extends TaskDefinition { type: string; @@ -206,8 +201,8 @@ export class CppBuildTaskProvider implements TaskProvider { return task; }; - async ensureBuildTaskExists(taskLabel: string): Promise { - const rawTasksJson: any = await getRawTasksJson(); + public async ensureBuildTaskExists(taskLabel: string): Promise { + const rawTasksJson: any = await this.getRawTasksJson(); // Ensure that the task exists in the user's task.json. Task will not be found otherwise. if (!rawTasksJson.tasks) { @@ -249,13 +244,49 @@ export class CppBuildTaskProvider implements TaskProvider { // TODO: It's dangerous to overwrite this file. We could be wiping out comments. const settings: OtherSettings = new OtherSettings(); - const tasksJsonPath: string | undefined = getTasksJsonPath(); + const tasksJsonPath: string | undefined = this.getTasksJsonPath(); if (!tasksJsonPath) { throw new Error("Failed to get tasksJsonPath in ensureBuildTaskExists()"); } await util.writeFileText(tasksJsonPath, JSON.stringify(rawTasksJson, null, settings.editorTabSize)); } + + public async ensureDebugConfigExists(configName: string): Promise { + const launchJsonPath: string | undefined = this.getLaunchJsonPath(); + if (!launchJsonPath) { + throw new Error("Failed to get launchJsonPath in ensureDebugConfigExists()"); + } + + const rawLaunchJson: any = await this.getRawLaunchJson(); + // Ensure that the debug configurations exists in the user's launch.json. Config will not be found otherwise. + if (!rawLaunchJson || !rawLaunchJson.configurations) { + throw new Error(`Configuration '${configName}' is missing in 'launch.json'.`); + } + const selectedConfig: Task | undefined = rawLaunchJson.configurations.find((config: any) => config.name && config.name === configName); + if (!selectedConfig) { + throw new Error(`Configuration '${configName}' is missing in 'launch.json'.`); + } + return; + } + + private getLaunchJsonPath(): string | undefined { + return util.getJsonPath("launch.json"); + } + + private getTasksJsonPath(): string | undefined { + return util.getJsonPath("tasks.json"); + } + + private getRawLaunchJson(): Promise { + const path: string | undefined = this.getLaunchJsonPath(); + return util.getRawJson(path); + } + + private getRawTasksJson(): Promise { + const path: string | undefined = this.getTasksJsonPath(); + return util.getRawJson(path); + } } class CustomBuildTaskTerminal implements Pseudoterminal { @@ -337,36 +368,4 @@ class CustomBuildTaskTerminal implements Pseudoterminal { "workspaceFolder": fileDir.uri.fsPath }; } -} - -export async function getRawTasksJson(): Promise { - const path: string | undefined = getTasksJsonPath(); - if (!path) { - return {}; - } - const fileExists: boolean = await util.checkFileExists(path); - if (!fileExists) { - return {}; - } - - const fileContents: string = await util.readFileText(path); - let rawTasks: any = {}; - try { - rawTasks = jsonc.parse(fileContents); - } catch (error) { - throw new Error(failedToParseTasksJson); - } - return rawTasks; -} - -export function getTasksJsonPath(): string | undefined { - const editor: TextEditor | undefined = window.activeTextEditor; - if (!editor) { - return undefined; - } - const folder: WorkspaceFolder | undefined = workspace.getWorkspaceFolder(editor.document.uri); - if (!folder) { - return undefined; - } - return path.join(folder.uri.fsPath, ".vscode", "tasks.json"); -} +} \ No newline at end of file diff --git a/Extension/src/common.ts b/Extension/src/common.ts index ed76537e9..1a4f4490b 100644 --- a/Extension/src/common.ts +++ b/Extension/src/common.ts @@ -26,6 +26,8 @@ import * as jsonc from 'comment-json'; nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })(); const localize: nls.LocalizeFunc = nls.loadMessageBundle(); +export const failedToParseJson: string = localize("failed.to.parse.json", "Failed to parse json file, possibly due to comments or trailing commas."); + export type Mutable = { // eslint-disable-next-line @typescript-eslint/array-type @@ -59,17 +61,7 @@ export function getRawPackageJson(): any { return rawPackageJson; } -export async function getRawLaunchJson(): Promise { - const path: string | undefined = getLaunchJsonPath(); - return getRawJson(path); -} - -export async function getRawTasksJson(): Promise { - const path: string | undefined = getTasksJsonPath(); - return getRawJson(path); -} - -async function getRawJson(path: string | undefined): Promise { +export async function getRawJson(path: string | undefined): Promise { if (!path) { return {}; } @@ -79,80 +71,13 @@ async function getRawJson(path: string | undefined): Promise { } const fileContents: string = await readFileText(path); - let rawTasks: any = {}; + let rawElement: any = {}; try { - rawTasks = jsonc.parse(fileContents); + rawElement = jsonc.parse(fileContents); } catch (error) { - throw new Error(failedToParseTasksJson); - } - return rawTasks; -} - -export async function ensureDebugConfigExists(configName: string): Promise { - const launchJsonPath: string | undefined = getLaunchJsonPath(); - if (!launchJsonPath) { - throw new Error("Failed to get launchJsonPath in ensureDebugConfigExists()"); + throw new Error(failedToParseJson); } - - const rawLaunchJson: any = await getRawLaunchJson(); - // Ensure that the debug configurations exists in the user's launch.json. Config will not be found otherwise. - if (!rawLaunchJson || !rawLaunchJson.configurations) { - throw new Error(`Configuration '${configName}' is missing in 'launch.json'.`); - } - const selectedConfig: vscode.Task | undefined = rawLaunchJson.configurations.find((config: any) => config.name && config.name === configName); - if (!selectedConfig) { - throw new Error(`Configuration '${configName}' is missing in 'launch.json'.`); - } - return; -} - -export async function ensureBuildTaskExists(taskLabel: string): Promise { - const rawTasksJson: any = await getRawTasksJson(); - - // Ensure that the task exists in the user's task.json. Task will not be found otherwise. - if (!rawTasksJson.tasks) { - rawTasksJson.tasks = new Array(); - } - // Find or create the task which should be created based on the selected "debug configuration". - let selectedTask: vscode.Task | undefined = rawTasksJson.tasks.find((task: any) => task.label && task.label === taskLabel); - if (selectedTask) { - return; - } - - const buildTasks: vscode.Task[] = await getBuildTasks(false, true); - selectedTask = buildTasks.find(task => task.name === taskLabel); - console.assert(selectedTask); - if (!selectedTask) { - throw new Error("Failed to get selectedTask in ensureBuildTaskExists()"); - } - - rawTasksJson.version = "2.0.0"; - - // Modify the current default task - rawTasksJson.tasks.forEach((task: any) => { - if (task.label === selectedTask?.definition.label) { - task.group = { kind: "build", "isDefault": true }; - } else if (task.group.kind && task.group.kind === "build" && task.group.isDefault && task.group.isDefault === true) { - task.group = "build"; - } - }); - - if (!rawTasksJson.tasks.find((task: any) => task.label === selectedTask?.definition.label)) { - const newTask: any = { - ...selectedTask.definition, - problemMatcher: selectedTask.problemMatchers, - group: { kind: "build", "isDefault": true } - }; - rawTasksJson.tasks.push(newTask); - } - - const settings: OtherSettings = new OtherSettings(); - const tasksJsonPath: string | undefined = getTasksJsonPath(); - if (!tasksJsonPath) { - throw new Error("Failed to get tasksJsonPath in ensureBuildTaskExists()"); - } - - await writeFileText(tasksJsonPath, jsonc.stringify(rawTasksJson, null, settings.editorTabSize)); + return rawElement; } export function fileIsCOrCppSource(file: string): boolean { @@ -183,15 +108,7 @@ export function getPackageJsonPath(): string { return getExtensionFilePath("package.json"); } -export function getLaunchJsonPath(): string | undefined { - return getJsonPath("launch.json"); -} - -export function getTasksJsonPath(): string | undefined { - return getJsonPath("tasks.json"); -} - -function getJsonPath(jsonFilaName: string): string | undefined { +export function getJsonPath(jsonFilaName: string): string | undefined { const editor: vscode.TextEditor | undefined = vscode.window.activeTextEditor; if (!editor) { return undefined; From 4e106cfdadb8ea43b045c59358c64effda27caff Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Thu, 10 Sep 2020 15:20:44 -0700 Subject: [PATCH 52/55] add new line --- Extension/src/LanguageServer/cppBuildTaskProvider.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Extension/src/LanguageServer/cppBuildTaskProvider.ts b/Extension/src/LanguageServer/cppBuildTaskProvider.ts index 1f4226572..7807824ad 100644 --- a/Extension/src/LanguageServer/cppBuildTaskProvider.ts +++ b/Extension/src/LanguageServer/cppBuildTaskProvider.ts @@ -368,4 +368,4 @@ class CustomBuildTaskTerminal implements Pseudoterminal { "workspaceFolder": fileDir.uri.fsPath }; } -} \ No newline at end of file +} From 1d8183eba6df64bc70ea395c5473b08e8aea4292 Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Thu, 10 Sep 2020 17:51:35 -0700 Subject: [PATCH 53/55] adapt to the new Vs Code API --- Extension/package.json | 7 +- Extension/package.nls.json | 3 +- .../LanguageServer/cppBuildTaskProvider.ts | 27 +- Extension/src/vscode.proposed.d.ts | 1775 ----------------- 4 files changed, 22 insertions(+), 1790 deletions(-) delete mode 100644 Extension/src/vscode.proposed.d.ts diff --git a/Extension/package.json b/Extension/package.json index 32810f336..97d414b22 100644 --- a/Extension/package.json +++ b/Extension/package.json @@ -6,13 +6,12 @@ "publisher": "ms-vscode", "icon": "LanguageCCPP_color_128x.png", "readme": "README.md", - "enableProposedApi": true, "author": { "name": "Microsoft Corporation" }, "license": "SEE LICENSE IN LICENSE.txt", "engines": { - "vscode": "^1.44.0" + "vscode": "^1.49.0" }, "bugs": { "url": "https://github.com/Microsoft/vscode-cpptools/issues", @@ -72,6 +71,10 @@ "description": "%c_cpp.taskDefinitions.options.cwd.description%" } } + }, + "detail": { + "type": "string", + "description": "%c_cpp.taskDefinitions.detail.description%" } } } diff --git a/Extension/package.nls.json b/Extension/package.nls.json index 33fd14c47..1d210577f 100644 --- a/Extension/package.nls.json +++ b/Extension/package.nls.json @@ -224,5 +224,6 @@ "c_cpp.taskDefinitions.command.description": "The path to either a compiler or script that performs compilation.", "c_cpp.taskDefinitions.args.description": "Additional arguments to pass to the compiler or compilation script.", "c_cpp.taskDefinitions.options.description": "Additional command options.", - "c_cpp.taskDefinitions.options.cwd.description": "The current working directory of the executed program or script. If omitted Code's current workspace root is used." + "c_cpp.taskDefinitions.options.cwd.description": "The current working directory of the executed program or script. If omitted Code's current workspace root is used.", + "c_cpp.taskDefinitions.detail.description": "Additional details of the task." } diff --git a/Extension/src/LanguageServer/cppBuildTaskProvider.ts b/Extension/src/LanguageServer/cppBuildTaskProvider.ts index 7807824ad..a652aa6b8 100644 --- a/Extension/src/LanguageServer/cppBuildTaskProvider.ts +++ b/Extension/src/LanguageServer/cppBuildTaskProvider.ts @@ -4,7 +4,7 @@ * ------------------------------------------------------------------------------------------ */ import * as path from 'path'; import { - TaskDefinition, Task2 as Task, TaskGroup, WorkspaceFolder, ShellExecution, Uri, workspace, + TaskDefinition, Task, TaskGroup, WorkspaceFolder, ShellExecution, Uri, workspace, TaskProvider, TaskScope, CustomExecution, ProcessExecution, TextEditor, Pseudoterminal, EventEmitter, Event, TerminalDimensions, window } from 'vscode'; import * as os from 'os'; @@ -24,14 +24,18 @@ export interface CppBuildTaskDefinition extends TaskDefinition { options: cp.ExecOptions | undefined; } +export class CppBuildTask extends Task { + detail?: string; +} + export class CppBuildTaskProvider implements TaskProvider { static CppBuildScriptType: string = 'cppbuild'; static CppBuildSourceStr: string = "C/C++"; - private tasks: Task[] | undefined; + private tasks: CppBuildTask[] | undefined; constructor() { } - public async provideTasks(): Promise { + public async provideTasks(): Promise { if (this.tasks) { return this.tasks; } @@ -39,7 +43,7 @@ export class CppBuildTaskProvider implements TaskProvider { } // Resolves a task that has no [`execution`](#Task.execution) set. - public resolveTask(_task: Task): Task | undefined { + public resolveTask(_task: CppBuildTask): CppBuildTask | undefined { const execution: ProcessExecution | ShellExecution | CustomExecution | undefined = _task.execution; if (!execution) { const definition: CppBuildTaskDefinition = _task.definition; @@ -50,12 +54,12 @@ export class CppBuildTaskProvider implements TaskProvider { } // Generate tasks to build the current file based on the user's detected compilers, the user's compilerPath setting, and the current file's extension. - public async getTasks(appendSourceToName: boolean): Promise { + public async getTasks(appendSourceToName: boolean): Promise { if (this.tasks !== undefined) { return this.tasks; } const editor: TextEditor | undefined = window.activeTextEditor; - const emptyTasks: Task[] = []; + const emptyTasks: CppBuildTask[] = []; if (!editor) { return emptyTasks; } @@ -136,7 +140,7 @@ export class CppBuildTaskProvider implements TaskProvider { } // Create a build task per compiler path - let result: Task[] = []; + let result: CppBuildTask[] = []; // Tasks for known compiler paths if (knownCompilerPaths) { result = knownCompilerPaths.map(compilerPath => this.getTask(compilerPath, appendSourceToName, undefined)); @@ -189,7 +193,7 @@ export class CppBuildTaskProvider implements TaskProvider { } const scope: TaskScope = TaskScope.Workspace; - const task: Task = new Task(definition, scope, taskLabel, CppBuildTaskProvider.CppBuildSourceStr, + const task: CppBuildTask = new Task(definition, scope, taskLabel, CppBuildTaskProvider.CppBuildSourceStr, new CustomExecution(async (): Promise => // When the task is executed, this callback will run. Here, we setup for running the task. new CustomBuildTaskTerminal(resolvedcompilerPath, args, options) @@ -209,12 +213,12 @@ export class CppBuildTaskProvider implements TaskProvider { rawTasksJson.tasks = new Array(); } // Find or create the task which should be created based on the selected "debug configuration". - let selectedTask: Task | undefined = rawTasksJson.tasks.find((task: any) => task.label && task.label === taskLabel); + let selectedTask: CppBuildTask | undefined = rawTasksJson.tasks.find((task: any) => task.label && task.label === taskLabel); if (selectedTask) { return; } - const buildTasks: Task[] = await this.getTasks(true); + const buildTasks: CppBuildTask[] = await this.getTasks(true); selectedTask = buildTasks.find(task => task.name === taskLabel); console.assert(selectedTask); if (!selectedTask) { @@ -242,7 +246,6 @@ export class CppBuildTaskProvider implements TaskProvider { rawTasksJson.tasks.push(newTask); } - // TODO: It's dangerous to overwrite this file. We could be wiping out comments. const settings: OtherSettings = new OtherSettings(); const tasksJsonPath: string | undefined = this.getTasksJsonPath(); if (!tasksJsonPath) { @@ -263,7 +266,7 @@ export class CppBuildTaskProvider implements TaskProvider { if (!rawLaunchJson || !rawLaunchJson.configurations) { throw new Error(`Configuration '${configName}' is missing in 'launch.json'.`); } - const selectedConfig: Task | undefined = rawLaunchJson.configurations.find((config: any) => config.name && config.name === configName); + const selectedConfig: any | undefined = rawLaunchJson.configurations.find((config: any) => config.name && config.name === configName); if (!selectedConfig) { throw new Error(`Configuration '${configName}' is missing in 'launch.json'.`); } diff --git a/Extension/src/vscode.proposed.d.ts b/Extension/src/vscode.proposed.d.ts deleted file mode 100644 index d49507f51..000000000 --- a/Extension/src/vscode.proposed.d.ts +++ /dev/null @@ -1,1775 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -/** - * This is the place for API experiments and proposals. - * These API are NOT stable and subject to change. They are only available in the Insiders - * distribution and CANNOT be used in published extensions. - * - * To test these API in local environment: - * - Use Insiders release of VS Code. - * - Add `"enableProposedApi": true` to your package.json. - * - Copy this file to your project. - */ - -declare module 'vscode' { - - // #region auth provider: https://github.com/microsoft/vscode/issues/88309 - - /** - * An [event](#Event) which fires when an [AuthenticationSession](#AuthenticationSession) is added, removed, or changed. - */ - export interface AuthenticationProviderAuthenticationSessionsChangeEvent { - /** - * The ids of the [AuthenticationSession](#AuthenticationSession)s that have been added. - */ - readonly added: ReadonlyArray; - - /** - * The ids of the [AuthenticationSession](#AuthenticationSession)s that have been removed. - */ - readonly removed: ReadonlyArray; - - /** - * The ids of the [AuthenticationSession](#AuthenticationSession)s that have been changed. - */ - readonly changed: ReadonlyArray; - } - - - - //#endregion - - //#region @alexdima - resolvers - - export interface RemoteAuthorityResolverContext { - resolveAttempt: number; - } - - export class ResolvedAuthority { - readonly host: string; - readonly port: number; - - constructor(host: string, port: number); - } - - export interface ResolvedOptions { - extensionHostEnv?: { [key: string]: string | null; }; - } - - export interface TunnelOptions { - remoteAddress: { port: number, host: string; }; - // The desired local port. If this port can't be used, then another will be chosen. - localAddressPort?: number; - label?: string; - } - - export interface TunnelDescription { - remoteAddress: { port: number, host: string; }; - //The complete local address(ex. localhost:1234) - localAddress: { port: number, host: string; } | string; - } - - export interface Tunnel extends TunnelDescription { - // Implementers of Tunnel should fire onDidDispose when dispose is called. - onDidDispose: Event; - dispose(): void; - } - - /** - * Used as part of the ResolverResult if the extension has any candidate, - * published, or forwarded ports. - */ - export interface TunnelInformation { - /** - * Tunnels that are detected by the extension. The remotePort is used for display purposes. - * The localAddress should be the complete local address (ex. localhost:1234) for connecting to the port. Tunnels provided through - * detected are read-only from the forwarded ports UI. - */ - environmentTunnels?: TunnelDescription[]; - - } - - export type ResolverResult = ResolvedAuthority & ResolvedOptions & TunnelInformation; - - export class RemoteAuthorityResolverError extends Error { - static NotAvailable(message?: string, handled?: boolean): RemoteAuthorityResolverError; - static TemporarilyNotAvailable(message?: string): RemoteAuthorityResolverError; - - constructor(message?: string); - } - - export interface RemoteAuthorityResolver { - resolve(authority: string, context: RemoteAuthorityResolverContext): ResolverResult | Thenable; - /** - * Can be optionally implemented if the extension can forward ports better than the core. - * When not implemented, the core will use its default forwarding logic. - * When implemented, the core will use this to forward ports. - */ - tunnelFactory?: (tunnelOptions: TunnelOptions) => Thenable | undefined; - - /** - * Provides filtering for candidate ports. - */ - showCandidatePort?: (host: string, port: number, detail: string) => Thenable; - } - - export namespace workspace { - /** - * Forwards a port. If the current resolver implements RemoteAuthorityResolver:forwardPort then that will be used to make the tunnel. - * By default, openTunnel only support localhost; however, RemoteAuthorityResolver:tunnelFactory can be used to support other ips. - * - * @throws When run in an environment without a remote. - * - * @param tunnelOptions The `localPort` is a suggestion only. If that port is not available another will be chosen. - */ - export function openTunnel(tunnelOptions: TunnelOptions): Thenable; - - /** - * Gets an array of the currently available tunnels. This does not include environment tunnels, only tunnels that have been created by the user. - * Note that these are of type TunnelDescription and cannot be disposed. - */ - export let tunnels: Thenable; - - /** - * Fired when the list of tunnels has changed. - */ - export const onDidChangeTunnels: Event; - } - - export interface ResourceLabelFormatter { - scheme: string; - authority?: string; - formatting: ResourceLabelFormatting; - } - - export interface ResourceLabelFormatting { - label: string; // myLabel:/${path} - // For historic reasons we use an or string here. Once we finalize this API we should start using enums instead and adopt it in extensions. - // eslint-disable-next-line vscode-dts-literal-or-types - separator: '/' | '\\' | ''; - tildify?: boolean; - normalizeDriveLetter?: boolean; - workspaceSuffix?: string; - authorityPrefix?: string; - stripPathStartingSeparator?: boolean; - } - - export namespace workspace { - export function registerRemoteAuthorityResolver(authorityPrefix: string, resolver: RemoteAuthorityResolver): Disposable; - export function registerResourceLabelFormatter(formatter: ResourceLabelFormatter): Disposable; - } - - //#endregion - - //#region editor insets: https://github.com/microsoft/vscode/issues/85682 - - export interface WebviewEditorInset { - readonly editor: TextEditor; - readonly line: number; - readonly height: number; - readonly webview: Webview; - readonly onDidDispose: Event; - dispose(): void; - } - - export namespace window { - export function createWebviewTextEditorInset(editor: TextEditor, line: number, height: number, options?: WebviewOptions): WebviewEditorInset; - } - - //#endregion - - //#region read/write in chunks: https://github.com/microsoft/vscode/issues/84515 - - export interface FileSystemProvider { - open?(resource: Uri, options: { create: boolean; }): number | Thenable; - close?(fd: number): void | Thenable; - read?(fd: number, pos: number, data: Uint8Array, offset: number, length: number): number | Thenable; - write?(fd: number, pos: number, data: Uint8Array, offset: number, length: number): number | Thenable; - } - - //#endregion - - //#region TextSearchProvider: https://github.com/microsoft/vscode/issues/59921 - - /** - * The parameters of a query for text search. - */ - export interface TextSearchQuery { - /** - * The text pattern to search for. - */ - pattern: string; - - /** - * Whether or not `pattern` should match multiple lines of text. - */ - isMultiline?: boolean; - - /** - * Whether or not `pattern` should be interpreted as a regular expression. - */ - isRegExp?: boolean; - - /** - * Whether or not the search should be case-sensitive. - */ - isCaseSensitive?: boolean; - - /** - * Whether or not to search for whole word matches only. - */ - isWordMatch?: boolean; - } - - /** - * A file glob pattern to match file paths against. - * TODO@roblourens merge this with the GlobPattern docs/definition in vscode.d.ts. - * @see [GlobPattern](#GlobPattern) - */ - export type GlobString = string; - - /** - * Options common to file and text search - */ - export interface SearchOptions { - /** - * The root folder to search within. - */ - folder: Uri; - - /** - * Files that match an `includes` glob pattern should be included in the search. - */ - includes: GlobString[]; - - /** - * Files that match an `excludes` glob pattern should be excluded from the search. - */ - excludes: GlobString[]; - - /** - * Whether external files that exclude files, like .gitignore, should be respected. - * See the vscode setting `"search.useIgnoreFiles"`. - */ - useIgnoreFiles: boolean; - - /** - * Whether symlinks should be followed while searching. - * See the vscode setting `"search.followSymlinks"`. - */ - followSymlinks: boolean; - - /** - * Whether global files that exclude files, like .gitignore, should be respected. - * See the vscode setting `"search.useGlobalIgnoreFiles"`. - */ - useGlobalIgnoreFiles: boolean; - } - - /** - * Options to specify the size of the result text preview. - * These options don't affect the size of the match itself, just the amount of preview text. - */ - export interface TextSearchPreviewOptions { - /** - * The maximum number of lines in the preview. - * Only search providers that support multiline search will ever return more than one line in the match. - */ - matchLines: number; - - /** - * The maximum number of characters included per line. - */ - charsPerLine: number; - } - - /** - * Options that apply to text search. - */ - export interface TextSearchOptions extends SearchOptions { - /** - * The maximum number of results to be returned. - */ - maxResults: number; - - /** - * Options to specify the size of the result text preview. - */ - previewOptions?: TextSearchPreviewOptions; - - /** - * Exclude files larger than `maxFileSize` in bytes. - */ - maxFileSize?: number; - - /** - * Interpret files using this encoding. - * See the vscode setting `"files.encoding"` - */ - encoding?: string; - - /** - * Number of lines of context to include before each match. - */ - beforeContext?: number; - - /** - * Number of lines of context to include after each match. - */ - afterContext?: number; - } - - /** - * Information collected when text search is complete. - */ - export interface TextSearchComplete { - /** - * Whether the search hit the limit on the maximum number of search results. - * `maxResults` on [`TextSearchOptions`](#TextSearchOptions) specifies the max number of results. - * - If exactly that number of matches exist, this should be false. - * - If `maxResults` matches are returned and more exist, this should be true. - * - If search hits an internal limit which is less than `maxResults`, this should be true. - */ - limitHit?: boolean; - } - - /** - * A preview of the text result. - */ - export interface TextSearchMatchPreview { - /** - * The matching lines of text, or a portion of the matching line that contains the match. - */ - text: string; - - /** - * The Range within `text` corresponding to the text of the match. - * The number of matches must match the TextSearchMatch's range property. - */ - matches: Range | Range[]; - } - - /** - * A match from a text search - */ - export interface TextSearchMatch { - /** - * The uri for the matching document. - */ - uri: Uri; - - /** - * The range of the match within the document, or multiple ranges for multiple matches. - */ - ranges: Range | Range[]; - - /** - * A preview of the text match. - */ - preview: TextSearchMatchPreview; - } - - /** - * A line of context surrounding a TextSearchMatch. - */ - export interface TextSearchContext { - /** - * The uri for the matching document. - */ - uri: Uri; - - /** - * One line of text. - * previewOptions.charsPerLine applies to this - */ - text: string; - - /** - * The line number of this line of context. - */ - lineNumber: number; - } - - export type TextSearchResult = TextSearchMatch | TextSearchContext; - - /** - * A TextSearchProvider provides search results for text results inside files in the workspace. - */ - export interface TextSearchProvider { - /** - * Provide results that match the given text pattern. - * @param query The parameters for this query. - * @param options A set of options to consider while searching. - * @param progress A progress callback that must be invoked for all results. - * @param token A cancellation token. - */ - provideTextSearchResults(query: TextSearchQuery, options: TextSearchOptions, progress: Progress, token: CancellationToken): ProviderResult; - } - - //#endregion - - //#region FileSearchProvider: https://github.com/microsoft/vscode/issues/73524 - - /** - * The parameters of a query for file search. - */ - export interface FileSearchQuery { - /** - * The search pattern to match against file paths. - */ - pattern: string; - } - - /** - * Options that apply to file search. - */ - export interface FileSearchOptions extends SearchOptions { - /** - * The maximum number of results to be returned. - */ - maxResults?: number; - - /** - * A CancellationToken that represents the session for this search query. If the provider chooses to, this object can be used as the key for a cache, - * and searches with the same session object can search the same cache. When the token is cancelled, the session is complete and the cache can be cleared. - */ - session?: CancellationToken; - } - - /** - * A FileSearchProvider provides search results for files in the given folder that match a query string. It can be invoked by quickopen or other extensions. - * - * A FileSearchProvider is the more powerful of two ways to implement file search in VS Code. Use a FileSearchProvider if you wish to search within a folder for - * all files that match the user's query. - * - * The FileSearchProvider will be invoked on every keypress in quickopen. When `workspace.findFiles` is called, it will be invoked with an empty query string, - * and in that case, every file in the folder should be returned. - */ - export interface FileSearchProvider { - /** - * Provide the set of files that match a certain file path pattern. - * @param query The parameters for this query. - * @param options A set of options to consider while searching files. - * @param token A cancellation token. - */ - provideFileSearchResults(query: FileSearchQuery, options: FileSearchOptions, token: CancellationToken): ProviderResult; - } - - export namespace workspace { - /** - * Register a search provider. - * - * Only one provider can be registered per scheme. - * - * @param scheme The provider will be invoked for workspace folders that have this file scheme. - * @param provider The provider. - * @return A [disposable](#Disposable) that unregisters this provider when being disposed. - */ - export function registerFileSearchProvider(scheme: string, provider: FileSearchProvider): Disposable; - - /** - * Register a text search provider. - * - * Only one provider can be registered per scheme. - * - * @param scheme The provider will be invoked for workspace folders that have this file scheme. - * @param provider The provider. - * @return A [disposable](#Disposable) that unregisters this provider when being disposed. - */ - export function registerTextSearchProvider(scheme: string, provider: TextSearchProvider): Disposable; - } - - //#endregion - - //#region findTextInFiles: https://github.com/microsoft/vscode/issues/59924 - - /** - * Options that can be set on a findTextInFiles search. - */ - export interface FindTextInFilesOptions { - /** - * A [glob pattern](#GlobPattern) that defines the files to search for. The glob pattern - * will be matched against the file paths of files relative to their workspace. Use a [relative pattern](#RelativePattern) - * to restrict the search results to a [workspace folder](#WorkspaceFolder). - */ - include?: GlobPattern; - - /** - * A [glob pattern](#GlobPattern) that defines files and folders to exclude. The glob pattern - * will be matched against the file paths of resulting matches relative to their workspace. When `undefined`, default excludes will - * apply. - */ - exclude?: GlobPattern; - - /** - * Whether to use the default and user-configured excludes. Defaults to true. - */ - useDefaultExcludes?: boolean; - - /** - * The maximum number of results to search for - */ - maxResults?: number; - - /** - * Whether external files that exclude files, like .gitignore, should be respected. - * See the vscode setting `"search.useIgnoreFiles"`. - */ - useIgnoreFiles?: boolean; - - /** - * Whether global files that exclude files, like .gitignore, should be respected. - * See the vscode setting `"search.useGlobalIgnoreFiles"`. - */ - useGlobalIgnoreFiles?: boolean; - - /** - * Whether symlinks should be followed while searching. - * See the vscode setting `"search.followSymlinks"`. - */ - followSymlinks?: boolean; - - /** - * Interpret files using this encoding. - * See the vscode setting `"files.encoding"` - */ - encoding?: string; - - /** - * Options to specify the size of the result text preview. - */ - previewOptions?: TextSearchPreviewOptions; - - /** - * Number of lines of context to include before each match. - */ - beforeContext?: number; - - /** - * Number of lines of context to include after each match. - */ - afterContext?: number; - } - - export namespace workspace { - /** - * Search text in files across all [workspace folders](#workspace.workspaceFolders) in the workspace. - * @param query The query parameters for the search - the search string, whether it's case-sensitive, or a regex, or matches whole words. - * @param callback A callback, called for each result - * @param token A token that can be used to signal cancellation to the underlying search engine. - * @return A thenable that resolves when the search is complete. - */ - export function findTextInFiles(query: TextSearchQuery, callback: (result: TextSearchResult) => void, token?: CancellationToken): Thenable; - - /** - * Search text in files across all [workspace folders](#workspace.workspaceFolders) in the workspace. - * @param query The query parameters for the search - the search string, whether it's case-sensitive, or a regex, or matches whole words. - * @param options An optional set of query options. Include and exclude patterns, maxResults, etc. - * @param callback A callback, called for each result - * @param token A token that can be used to signal cancellation to the underlying search engine. - * @return A thenable that resolves when the search is complete. - */ - export function findTextInFiles(query: TextSearchQuery, options: FindTextInFilesOptions, callback: (result: TextSearchResult) => void, token?: CancellationToken): Thenable; - } - - //#endregion - - //#region diff command: https://github.com/microsoft/vscode/issues/84899 - - /** - * The contiguous set of modified lines in a diff. - */ - export interface LineChange { - readonly originalStartLineNumber: number; - readonly originalEndLineNumber: number; - readonly modifiedStartLineNumber: number; - readonly modifiedEndLineNumber: number; - } - - export namespace commands { - - /** - * Registers a diff information command that can be invoked via a keyboard shortcut, - * a menu item, an action, or directly. - * - * Diff information commands are different from ordinary [commands](#commands.registerCommand) as - * they only execute when there is an active diff editor when the command is called, and the diff - * information has been computed. Also, the command handler of an editor command has access to - * the diff information. - * - * @param command A unique identifier for the command. - * @param callback A command handler function with access to the [diff information](#LineChange). - * @param thisArg The `this` context used when invoking the handler function. - * @return Disposable which unregisters this command on disposal. - */ - export function registerDiffInformationCommand(command: string, callback: (diff: LineChange[], ...args: any[]) => any, thisArg?: any): Disposable; - } - - //#endregion - - //#region file-decorations: https://github.com/microsoft/vscode/issues/54938 - - export class Decoration { - letter?: string; - title?: string; - color?: ThemeColor; - priority?: number; - bubble?: boolean; - } - - export interface DecorationProvider { - onDidChangeDecorations: Event; - provideDecoration(uri: Uri, token: CancellationToken): ProviderResult; - } - - export namespace window { - export function registerDecorationProvider(provider: DecorationProvider): Disposable; - } - - //#endregion - - //#region debug - - export interface DebugSessionOptions { - /** - * Controls whether this session should run without debugging, thus ignoring breakpoints. - * When this property is not specified, the value from the parent session (if there is one) is used. - */ - noDebug?: boolean; - - /** - * Controls if the debug session's parent session is shown in the CALL STACK view even if it has only a single child. - * By default, the debug session will never hide its parent. - * If compact is true, debug sessions with a single child are hidden in the CALL STACK view to make the tree more compact. - */ - compact?: boolean; - } - - /** - * A DebugProtocolBreakpoint is an opaque stand-in type for the [Breakpoint](https://microsoft.github.io/debug-adapter-protocol/specification#Types_Breakpoint) type defined in the Debug Adapter Protocol. - */ - export interface DebugProtocolBreakpoint { - // Properties: see details [here](https://microsoft.github.io/debug-adapter-protocol/specification#Types_Breakpoint). - } - - export interface DebugSession { - getDebugProtocolBreakpoint(breakpoint: Breakpoint): DebugProtocolBreakpoint | undefined; - } - - // deprecated debug API - - export interface DebugConfigurationProvider { - /** - * Deprecated, use DebugAdapterDescriptorFactory.provideDebugAdapter instead. - * @deprecated Use DebugAdapterDescriptorFactory.createDebugAdapterDescriptor instead - */ - debugAdapterExecutable?(folder: WorkspaceFolder | undefined, token?: CancellationToken): ProviderResult; - } - - //#endregion - - //#region LogLevel: https://github.com/microsoft/vscode/issues/85992 - - /** - * @deprecated DO NOT USE, will be removed - */ - export enum LogLevel { - Trace = 1, - Debug = 2, - Info = 3, - Warning = 4, - Error = 5, - Critical = 6, - Off = 7 - } - - export namespace env { - /** - * @deprecated DO NOT USE, will be removed - */ - export const logLevel: LogLevel; - - /** - * @deprecated DO NOT USE, will be removed - */ - export const onDidChangeLogLevel: Event; - } - - //#endregion - - //#region @joaomoreno: SCM validation - - /** - * Represents the validation type of the Source Control input. - */ - export enum SourceControlInputBoxValidationType { - - /** - * Something not allowed by the rules of a language or other means. - */ - Error = 0, - - /** - * Something suspicious but allowed. - */ - Warning = 1, - - /** - * Something to inform about but not a problem. - */ - Information = 2 - } - - export interface SourceControlInputBoxValidation { - - /** - * The validation message to display. - */ - readonly message: string; - - /** - * The validation type. - */ - readonly type: SourceControlInputBoxValidationType; - } - - /** - * Represents the input box in the Source Control viewlet. - */ - export interface SourceControlInputBox { - - /** - * A validation function for the input box. It's possible to change - * the validation provider simply by setting this property to a different function. - */ - validateInput?(value: string, cursorPosition: number): ProviderResult; - } - - //#endregion - - //#region @joaomoreno: SCM selected provider - - export interface SourceControl { - - /** - * Whether the source control is selected. - */ - readonly selected: boolean; - - /** - * An event signaling when the selection state changes. - */ - readonly onDidChangeSelection: Event; - } - - //#endregion - - //#region Terminal data write event https://github.com/microsoft/vscode/issues/78502 - - export interface TerminalDataWriteEvent { - /** - * The [terminal](#Terminal) for which the data was written. - */ - readonly terminal: Terminal; - /** - * The data being written. - */ - readonly data: string; - } - - namespace window { - /** - * An event which fires when the terminal's child pseudo-device is written to (the shell). - * In other words, this provides access to the raw data stream from the process running - * within the terminal, including VT sequences. - */ - export const onDidWriteTerminalData: Event; - } - - //#endregion - - //#region Terminal dimensions property and change event https://github.com/microsoft/vscode/issues/55718 - - /** - * An [event](#Event) which fires when a [Terminal](#Terminal)'s dimensions change. - */ - export interface TerminalDimensionsChangeEvent { - /** - * The [terminal](#Terminal) for which the dimensions have changed. - */ - readonly terminal: Terminal; - /** - * The new value for the [terminal's dimensions](#Terminal.dimensions). - */ - readonly dimensions: TerminalDimensions; - } - - export namespace window { - /** - * An event which fires when the [dimensions](#Terminal.dimensions) of the terminal change. - */ - export const onDidChangeTerminalDimensions: Event; - } - - export interface Terminal { - /** - * The current dimensions of the terminal. This will be `undefined` immediately after the - * terminal is created as the dimensions are not known until shortly after the terminal is - * created. - */ - readonly dimensions: TerminalDimensions | undefined; - } - - //#endregion - - //#region @jrieken -> exclusive document filters - - export interface DocumentFilter { - exclusive?: boolean; - } - - //#endregion - - //#region @alexdima - OnEnter enhancement - export interface OnEnterRule { - /** - * This rule will only execute if the text above the this line matches this regular expression. - */ - oneLineAboveText?: RegExp; - } - //#endregion - - //#region Tree View: https://github.com/microsoft/vscode/issues/61313 - /** - * Label describing the [Tree item](#TreeItem) - */ - export interface TreeItemLabel { - - /** - * A human-readable string describing the [Tree item](#TreeItem). - */ - label: string; - - /** - * Ranges in the label to highlight. A range is defined as a tuple of two number where the - * first is the inclusive start index and the second the exclusive end index - */ - highlights?: [number, number][]; - - } - - // https://github.com/microsoft/vscode/issues/100741 - export interface TreeDataProvider { - resolveTreeItem?(element: T, item: TreeItem2): TreeItem2 | Thenable; - } - - export class TreeItem2 extends TreeItem { - /** - * Label describing this item. When `falsy`, it is derived from [resourceUri](#TreeItem.resourceUri). - */ - label?: string | TreeItemLabel | /* for compilation */ any; - - /** - * Content to be shown when you hover over the tree item. - */ - tooltip?: string | MarkdownString | /* for compilation */ any; - - /** - * @param label Label describing this item - * @param collapsibleState [TreeItemCollapsibleState](#TreeItemCollapsibleState) of the tree item. Default is [TreeItemCollapsibleState.None](#TreeItemCollapsibleState.None) - */ - constructor(label: TreeItemLabel, collapsibleState?: TreeItemCollapsibleState); - } - //#endregion - - //#region CustomExecution: https://github.com/microsoft/vscode/issues/81007 - /** - * A task to execute - */ - export class Task2 extends Task { - detail?: string; - } - - export class CustomExecution2 extends CustomExecution { - /** - * Constructs a CustomExecution task object. The callback will be executed the task is run, at which point the - * extension should return the Pseudoterminal it will "run in". The task should wait to do further execution until - * [Pseudoterminal.open](#Pseudoterminal.open) is called. Task cancellation should be handled using - * [Pseudoterminal.close](#Pseudoterminal.close). When the task is complete fire - * [Pseudoterminal.onDidClose](#Pseudoterminal.onDidClose). - * @param callback The callback that will be called when the task is started by a user. - */ - constructor(callback: (resolvedDefinition: TaskDefinition) => Thenable); - } - //#endregion - - //#region Task presentation group: https://github.com/microsoft/vscode/issues/47265 - export interface TaskPresentationOptions { - /** - * Controls whether the task is executed in a specific terminal group using split panes. - */ - group?: string; - } - //#endregion - - //#region Status bar item with ID and Name: https://github.com/microsoft/vscode/issues/74972 - - - - //#endregion - - //#region OnTypeRename: https://github.com/microsoft/vscode/issues/88424 - - /** - * The rename provider interface defines the contract between extensions and - * the live-rename feature. - */ - export interface OnTypeRenameProvider { - /** - * Provide a list of ranges that can be live renamed together. - * - * @param document The document in which the command was invoked. - * @param position The position at which the command was invoked. - * @param token A cancellation token. - * @return A list of ranges that can be live-renamed togehter. The ranges must have - * identical length and contain identical text content. The ranges cannot overlap. - */ - provideOnTypeRenameRanges(document: TextDocument, position: Position, token: CancellationToken): ProviderResult; - } - - namespace languages { - /** - * Register a rename provider that works on type. - * - * Multiple providers can be registered for a language. In that case providers are sorted - * by their [score](#languages.match) and the best-matching provider is used. Failure - * of the selected provider will cause a failure of the whole operation. - * - * @param selector A selector that defines the documents this provider is applicable to. - * @param provider An on type rename provider. - * @param stopPattern Stop on type renaming when input text matches the regular expression. Defaults to `^\s`. - * @return A [disposable](#Disposable) that unregisters this provider when being disposed. - */ - export function registerOnTypeRenameProvider(selector: DocumentSelector, provider: OnTypeRenameProvider, stopPattern?: RegExp): Disposable; - } - - //#endregion - - //#region Custom editor move https://github.com/microsoft/vscode/issues/86146 - - // TODO: Also for custom editor - - export interface CustomTextEditorProvider { - - /** - * Handle when the underlying resource for a custom editor is renamed. - * - * This allows the webview for the editor be preserved throughout the rename. If this method is not implemented, - * VS Code will destory the previous custom editor and create a replacement one. - * - * @param newDocument New text document to use for the custom editor. - * @param existingWebviewPanel Webview panel for the custom editor. - * @param token A cancellation token that indicates the result is no longer needed. - * - * @return Thenable indicating that the webview editor has been moved. - */ - moveCustomTextEditor?(newDocument: TextDocument, existingWebviewPanel: WebviewPanel, token: CancellationToken): Thenable; - } - - //#endregion - - //#region allow QuickPicks to skip sorting: https://github.com/microsoft/vscode/issues/73904 - - export interface QuickPick extends QuickInput { - /** - * An optional flag to sort the final results by index of first query match in label. Defaults to true. - */ - sortByLabel: boolean; - } - - //#endregion - - //#region @rebornix: Notebook - - export enum CellKind { - Markdown = 1, - Code = 2 - } - - export enum CellOutputKind { - Text = 1, - Error = 2, - Rich = 3 - } - - export interface CellStreamOutput { - outputKind: CellOutputKind.Text; - text: string; - } - - export interface CellErrorOutput { - outputKind: CellOutputKind.Error; - /** - * Exception Name - */ - ename: string; - /** - * Exception Value - */ - evalue: string; - /** - * Exception call stack - */ - traceback: string[]; - } - - export interface NotebookCellOutputMetadata { - /** - * Additional attributes of a cell metadata. - */ - custom?: { [key: string]: any }; - } - - export interface CellDisplayOutput { - outputKind: CellOutputKind.Rich; - /** - * { mime_type: value } - * - * Example: - * ```json - * { - * "outputKind": vscode.CellOutputKind.Rich, - * "data": { - * "text/html": [ - * "

Hello

" - * ], - * "text/plain": [ - * "" - * ] - * } - * } - */ - data: { [key: string]: any; }; - - readonly metadata?: NotebookCellOutputMetadata; - } - - export type CellOutput = CellStreamOutput | CellErrorOutput | CellDisplayOutput; - - export enum NotebookCellRunState { - Running = 1, - Idle = 2, - Success = 3, - Error = 4 - } - - export enum NotebookRunState { - Running = 1, - Idle = 2 - } - - export interface NotebookCellMetadata { - /** - * Controls if the content of a cell is editable or not. - */ - editable?: boolean; - - /** - * Controls if the cell is executable. - * This metadata is ignored for markdown cell. - */ - runnable?: boolean; - - /** - * Controls if the cell has a margin to support the breakpoint UI. - * This metadata is ignored for markdown cell. - */ - breakpointMargin?: boolean; - - /** - * Whether the [execution order](#NotebookCellMetadata.executionOrder) indicator will be displayed. - * Defaults to true. - */ - hasExecutionOrder?: boolean; - - /** - * The order in which this cell was executed. - */ - executionOrder?: number; - - /** - * A status message to be shown in the cell's status bar - */ - statusMessage?: string; - - /** - * The cell's current run state - */ - runState?: NotebookCellRunState; - - /** - * If the cell is running, the time at which the cell started running - */ - runStartTime?: number; - - /** - * The total duration of the cell's last run - */ - lastRunDuration?: number; - - /** - * Whether a code cell's editor is collapsed - */ - inputCollapsed?: boolean; - - /** - * Whether a code cell's outputs are collapsed - */ - outputCollapsed?: boolean; - - /** - * Additional attributes of a cell metadata. - */ - custom?: { [key: string]: any }; - } - - export interface NotebookCell { - readonly notebook: NotebookDocument; - readonly uri: Uri; - readonly cellKind: CellKind; - readonly document: TextDocument; - language: string; - outputs: CellOutput[]; - metadata: NotebookCellMetadata; - } - - export interface NotebookDocumentMetadata { - /** - * Controls if users can add or delete cells - * Defaults to true - */ - editable?: boolean; - - /** - * Controls whether the full notebook can be run at once. - * Defaults to true - */ - runnable?: boolean; - - /** - * Default value for [cell editable metadata](#NotebookCellMetadata.editable). - * Defaults to true. - */ - cellEditable?: boolean; - - /** - * Default value for [cell runnable metadata](#NotebookCellMetadata.runnable). - * Defaults to true. - */ - cellRunnable?: boolean; - - /** - * Default value for [cell hasExecutionOrder metadata](#NotebookCellMetadata.hasExecutionOrder). - * Defaults to true. - */ - cellHasExecutionOrder?: boolean; - - displayOrder?: GlobPattern[]; - - /** - * Additional attributes of the document metadata. - */ - custom?: { [key: string]: any }; - - /** - * The document's current run state - */ - runState?: NotebookRunState; - } - - export interface NotebookDocument { - readonly uri: Uri; - readonly fileName: string; - readonly viewType: string; - readonly isDirty: boolean; - readonly isUntitled: boolean; - readonly cells: NotebookCell[]; - languages: string[]; - displayOrder?: GlobPattern[]; - metadata: NotebookDocumentMetadata; - } - - export interface NotebookConcatTextDocument { - uri: Uri; - isClosed: boolean; - dispose(): void; - onDidChange: Event; - version: number; - getText(): string; - getText(range: Range): string; - - offsetAt(position: Position): number; - positionAt(offset: number): Position; - validateRange(range: Range): Range; - validatePosition(position: Position): Position; - - locationAt(positionOrRange: Position | Range): Location; - positionAt(location: Location): Position; - contains(uri: Uri): boolean - } - - export interface NotebookEditorCellEdit { - insert(index: number, content: string | string[], language: string, type: CellKind, outputs: CellOutput[], metadata: NotebookCellMetadata | undefined): void; - delete(index: number): void; - } - - export interface NotebookEditor { - /** - * The document associated with this notebook editor. - */ - readonly document: NotebookDocument; - - /** - * The primary selected cell on this notebook editor. - */ - readonly selection?: NotebookCell; - - /** - * The column in which this editor shows. - */ - viewColumn?: ViewColumn; - - /** - * Whether the panel is active (focused by the user). - */ - readonly active: boolean; - - /** - * Whether the panel is visible. - */ - readonly visible: boolean; - - /** - * Fired when the panel is disposed. - */ - readonly onDidDispose: Event; - - /** - * Active kernel used in the editor - */ - readonly kernel?: NotebookKernel; - - /** - * Fired when the output hosting webview posts a message. - */ - readonly onDidReceiveMessage: Event; - /** - * Post a message to the output hosting webview. - * - * Messages are only delivered if the editor is live. - * - * @param message Body of the message. This must be a string or other json serilizable object. - */ - postMessage(message: any): Thenable; - - /** - * Convert a uri for the local file system to one that can be used inside outputs webview. - */ - asWebviewUri(localResource: Uri): Uri; - - edit(callback: (editBuilder: NotebookEditorCellEdit) => void): Thenable; - } - - export interface NotebookOutputSelector { - mimeTypes?: string[]; - } - - export interface NotebookRenderRequest { - output: CellDisplayOutput; - mimeType: string; - outputId: string; - } - - export interface NotebookOutputRenderer { - /** - * - * @returns HTML fragment. We can probably return `CellOutput` instead of string ? - * - */ - render(document: NotebookDocument, request: NotebookRenderRequest): string; - - /** - * Call before HTML from the renderer is executed, and will be called for - * every editor associated with notebook documents where the renderer - * is or was used. - * - * The communication object will only send and receive messages to the - * render API, retrieved via `acquireNotebookRendererApi`, acquired with - * this specific renderer's ID. - * - * If you need to keep an association between the communication object - * and the document for use in the `render()` method, you can use a WeakMap. - */ - resolveNotebook?(document: NotebookDocument, communication: NotebookCommunication): void; - - readonly preloads?: Uri[]; - } - - export interface NotebookCellsChangeData { - readonly start: number; - readonly deletedCount: number; - readonly deletedItems: NotebookCell[]; - readonly items: NotebookCell[]; - } - - export interface NotebookCellsChangeEvent { - - /** - * The affected document. - */ - readonly document: NotebookDocument; - readonly changes: ReadonlyArray; - } - - export interface NotebookCellMoveEvent { - - /** - * The affected document. - */ - readonly document: NotebookDocument; - readonly index: number; - readonly newIndex: number; - } - - export interface NotebookCellOutputsChangeEvent { - - /** - * The affected document. - */ - readonly document: NotebookDocument; - readonly cells: NotebookCell[]; - } - - export interface NotebookCellLanguageChangeEvent { - - /** - * The affected document. - */ - readonly document: NotebookDocument; - readonly cell: NotebookCell; - readonly language: string; - } - - export interface NotebookCellMetadataChangeEvent { - readonly document: NotebookDocument; - readonly cell: NotebookCell; - } - - export interface NotebookCellData { - readonly cellKind: CellKind; - readonly source: string; - language: string; - outputs: CellOutput[]; - metadata: NotebookCellMetadata; - } - - export interface NotebookData { - readonly cells: NotebookCellData[]; - readonly languages: string[]; - readonly metadata: NotebookDocumentMetadata; - } - - interface NotebookDocumentContentChangeEvent { - - /** - * The document that the edit is for. - */ - readonly document: NotebookDocument; - } - - interface NotebookDocumentEditEvent { - - /** - * The document that the edit is for. - */ - readonly document: NotebookDocument; - - /** - * Undo the edit operation. - * - * This is invoked by VS Code when the user undoes this edit. To implement `undo`, your - * extension should restore the document and editor to the state they were in just before this - * edit was added to VS Code's internal edit stack by `onDidChangeCustomDocument`. - */ - undo(): Thenable | void; - - /** - * Redo the edit operation. - * - * This is invoked by VS Code when the user redoes this edit. To implement `redo`, your - * extension should restore the document and editor to the state they were in just after this - * edit was added to VS Code's internal edit stack by `onDidChangeCustomDocument`. - */ - redo(): Thenable | void; - - /** - * Display name describing the edit. - * - * This will be shown to users in the UI for undo/redo operations. - */ - readonly label?: string; - } - - interface NotebookDocumentBackup { - /** - * Unique identifier for the backup. - * - * This id is passed back to your extension in `openCustomDocument` when opening a notebook editor from a backup. - */ - readonly id: string; - - /** - * Delete the current backup. - * - * This is called by VS Code when it is clear the current backup is no longer needed, such as when a new backup - * is made or when the file is saved. - */ - delete(): void; - } - - interface NotebookDocumentBackupContext { - readonly destination: Uri; - } - - interface NotebookDocumentOpenContext { - readonly backupId?: string; - } - - /** - * Communication object passed to the {@link NotebookContentProvider} and - * {@link NotebookOutputRenderer} to communicate with the webview. - */ - export interface NotebookCommunication { - /** - * ID of the editor this object communicates with. A single notebook - * document can have multiple attached webviews and editors, when the - * notebook is split for instance. The editor ID lets you differentiate - * between them. - */ - readonly editorId: string; - - /** - * Fired when the output hosting webview posts a message. - */ - readonly onDidReceiveMessage: Event; - /** - * Post a message to the output hosting webview. - * - * Messages are only delivered if the editor is live. - * - * @param message Body of the message. This must be a string or other json serilizable object. - */ - postMessage(message: any): Thenable; - - /** - * Convert a uri for the local file system to one that can be used inside outputs webview. - */ - asWebviewUri(localResource: Uri): Uri; - } - - export interface NotebookContentProvider { - /** - * Content providers should always use [file system providers](#FileSystemProvider) to - * resolve the raw content for `uri` as the resouce is not necessarily a file on disk. - */ - openNotebook(uri: Uri, openContext: NotebookDocumentOpenContext): NotebookData | Promise; - resolveNotebook(document: NotebookDocument, webview: NotebookCommunication): Promise; - saveNotebook(document: NotebookDocument, cancellation: CancellationToken): Promise; - saveNotebookAs(targetResource: Uri, document: NotebookDocument, cancellation: CancellationToken): Promise; - readonly onDidChangeNotebook: Event; - backupNotebook(document: NotebookDocument, context: NotebookDocumentBackupContext, cancellation: CancellationToken): Promise; - - kernel?: NotebookKernel; - } - - export interface NotebookKernel { - readonly id?: string; - label: string; - description?: string; - isPreferred?: boolean; - preloads?: Uri[]; - executeCell(document: NotebookDocument, cell: NotebookCell): void; - cancelCellExecution(document: NotebookDocument, cell: NotebookCell): void; - executeAllCells(document: NotebookDocument): void; - cancelAllCellsExecution(document: NotebookDocument): void; - } - - export interface NotebookDocumentFilter { - viewType?: string; - filenamePattern?: GlobPattern; - excludeFileNamePattern?: GlobPattern; - } - - export interface NotebookKernelProvider { - onDidChangeKernels?: Event; - provideKernels(document: NotebookDocument, token: CancellationToken): ProviderResult; - resolveKernel?(kernel: T, document: NotebookDocument, webview: NotebookCommunication, token: CancellationToken): ProviderResult; - } - - export namespace notebook { - export function registerNotebookContentProvider( - notebookType: string, - provider: NotebookContentProvider - ): Disposable; - - export function registerNotebookKernelProvider( - selector: NotebookDocumentFilter, - provider: NotebookKernelProvider - ): Disposable; - - export function registerNotebookKernel( - id: string, - selectors: GlobPattern[], - kernel: NotebookKernel - ): Disposable; - - export function registerNotebookOutputRenderer( - id: string, - outputSelector: NotebookOutputSelector, - renderer: NotebookOutputRenderer - ): Disposable; - - export const onDidOpenNotebookDocument: Event; - export const onDidCloseNotebookDocument: Event; - export const onDidSaveNotebookDocument: Event; - - /** - * All currently known notebook documents. - */ - export const notebookDocuments: ReadonlyArray; - - export let visibleNotebookEditors: NotebookEditor[]; - export const onDidChangeVisibleNotebookEditors: Event; - - export let activeNotebookEditor: NotebookEditor | undefined; - export const onDidChangeActiveNotebookEditor: Event; - export const onDidChangeNotebookCells: Event; - export const onDidChangeCellOutputs: Event; - export const onDidChangeCellLanguage: Event; - export const onDidChangeCellMetadata: Event; - /** - * Create a document that is the concatenation of all notebook cells. By default all code-cells are included - * but a selector can be provided to narrow to down the set of cells. - * - * @param notebook - * @param selector - */ - export function createConcatTextDocument(notebook: NotebookDocument, selector?: DocumentSelector): NotebookConcatTextDocument; - - export const onDidChangeActiveNotebookKernel: Event<{ document: NotebookDocument, kernel: NotebookKernel | undefined }>; - } - - //#endregion - - //#region https://github.com/microsoft/vscode/issues/39441 - - export interface CompletionItem { - /** - * Will be merged into CompletionItem#label - */ - label2?: CompletionItemLabel; - } - - export interface CompletionItemLabel { - /** - * The function or variable. Rendered leftmost. - */ - name: string; - - /** - * The parameters without the return type. Render after `name`. - */ - parameters?: string; - - /** - * The fully qualified name, like package name or file path. Rendered after `signature`. - */ - qualifier?: string; - - /** - * The return-type of a function or type of a property/variable. Rendered rightmost. - */ - type?: string; - } - - //#endregion - - //#region @eamodio - timeline: https://github.com/microsoft/vscode/issues/84297 - - - export interface TimelineChangeEvent { - /** - * The [uri](#Uri) of the resource for which the timeline changed. - */ - uri: Uri; - - /** - * A flag which indicates whether the entire timeline should be reset. - */ - reset?: boolean; - } - - - export interface TimelineOptions { - /** - * A provider-defined cursor specifying the starting point of the timeline items that should be returned. - */ - cursor?: string; - - /** - * An optional maximum number timeline items or the all timeline items newer (inclusive) than the timestamp or id that should be returned. - * If `undefined` all timeline items should be returned. - */ - limit?: number | { timestamp: number; id?: string; }; - } - - - - //#endregion - - //#region https://github.com/microsoft/vscode/issues/91555 - - export enum StandardTokenType { - Other = 0, - Comment = 1, - String = 2, - RegEx = 4 - } - - export interface TokenInformation { - type: StandardTokenType; - range: Range; - } - - export namespace languages { - export function getTokenInformationAtPosition(document: TextDocument, position: Position): Promise; - } - - //#endregion - - //#region Support `scmResourceState` in `when` clauses #86180 https://github.com/microsoft/vscode/issues/86180 - - export interface SourceControlResourceState { - /** - * Context value of the resource state. This can be used to contribute resource specific actions. - * For example, if a resource is given a context value as `diffable`. When contributing actions to `scm/resourceState/context` - * using `menus` extension point, you can specify context value for key `scmResourceState` in `when` expressions, like `scmResourceState == diffable`. - * ``` - * "contributes": { - * "menus": { - * "scm/resourceState/context": [ - * { - * "command": "extension.diff", - * "when": "scmResourceState == diffable" - * } - * ] - * } - * } - * ``` - * This will show action `extension.diff` only for resources with `contextValue` is `diffable`. - */ - readonly contextValue?: string; - } - - //#endregion - //#region https://github.com/microsoft/vscode/issues/101857 - - export interface ExtensionContext { - - /** - * The uri of a directory in which the extension can create log files. - * The directory might not exist on disk and creation is up to the extension. However, - * the parent directory is guaranteed to be existent. - * - * @see [`workspace.fs`](#FileSystem) for how to read and write files and folders from - * an uri. - */ - readonly logUri: Uri; - - /** - * The uri of a workspace specific directory in which the extension - * can store private state. The directory might not exist and creation is - * up to the extension. However, the parent directory is guaranteed to be existent. - * The value is `undefined` when no workspace nor folder has been opened. - * - * Use [`workspaceState`](#ExtensionContext.workspaceState) or - * [`globalState`](#ExtensionContext.globalState) to store key value data. - * - * @see [`workspace.fs`](#FileSystem) for how to read and write files and folders from - * an uri. - */ - readonly storageUri: Uri | undefined; - - /** - * The uri of a directory in which the extension can store global state. - * The directory might not exist on disk and creation is - * up to the extension. However, the parent directory is guaranteed to be existent. - * - * Use [`globalState`](#ExtensionContext.globalState) to store key value data. - * - * @see [`workspace.fs`](#FileSystem) for how to read and write files and folders from - * an uri. - */ - readonly globalStorageUri: Uri; - - /** - * @deprecated Use [logUri](#ExtensionContext.logUri) instead. - */ - readonly logPath: string; - /** - * @deprecated Use [storagePath](#ExtensionContent.storageUri) instead. - */ - readonly storagePath: string | undefined; - /** - * @deprecated Use [globalStoragePath](#ExtensionContent.globalStorageUri) instead. - */ - readonly globalStoragePath: string; - } - - //#endregion - - //#region https://github.com/microsoft/vscode/issues/104436 - - export enum ExtensionRuntime { - /** - * The extension is running in a NodeJS extension host. Runtime access to NodeJS APIs is available. - */ - Node = 1, - /** - * The extension is running in a Webworker extension host. Runtime access is limited to Webworker APIs. - */ - Webworker = 2 - } - - export interface ExtensionContext { - readonly extensionRuntime: ExtensionRuntime; - } - - //#endregion - - - //#region https://github.com/microsoft/vscode/issues/102091 - - export interface TextDocument { - - /** - * The [notebook](#NotebookDocument) that contains this document as a notebook cell or `undefined` when - * the document is not contained by a notebook (this should be the more frequent case). - */ - notebook: NotebookDocument | undefined; - } - //#endregion -} \ No newline at end of file From b14b33d6bd839fa4edb4ead27c3988e71c7b0a16 Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Mon, 21 Sep 2020 12:37:43 -0700 Subject: [PATCH 54/55] linter error --- Extension/src/common.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/Extension/src/common.ts b/Extension/src/common.ts index bb9820ff6..8118d9ad7 100644 --- a/Extension/src/common.ts +++ b/Extension/src/common.ts @@ -17,7 +17,6 @@ import * as assert from 'assert'; import * as https from 'https'; import * as tmp from 'tmp'; import { ClientRequest, OutgoingHttpHeaders } from 'http'; - import { lookupString } from './nativeStrings'; import * as nls from 'vscode-nls'; import { Readable } from 'stream'; @@ -28,7 +27,6 @@ nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFo const localize: nls.LocalizeFunc = nls.loadMessageBundle(); export const failedToParseJson: string = localize("failed.to.parse.json", "Failed to parse json file, possibly due to comments or trailing commas."); - export type Mutable = { // eslint-disable-next-line @typescript-eslint/array-type -readonly [P in keyof T]: T[P] extends ReadonlyArray ? Mutable[] : Mutable From 2cb0b472af26ed255b27ab1e324a3bfe8f15505c Mon Sep 17 00:00:00 2001 From: Elaheh Rashedi Date: Tue, 22 Sep 2020 12:29:34 -0700 Subject: [PATCH 55/55] revert changelog --- Extension/CHANGELOG.md | 1 - Extension/package.nls.json | 10 +++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/Extension/CHANGELOG.md b/Extension/CHANGELOG.md index afed80a66..e9f12befe 100644 --- a/Extension/CHANGELOG.md +++ b/Extension/CHANGELOG.md @@ -74,7 +74,6 @@ * Add `quoteArgs` to `launch.json` schema. [PR #5639](https://github.com/microsoft/vscode-cpptools/pull/5639) * Add logs for a resolved `launch.json` if "engineLogging" is enabled. [PR #5644](https://github.com/microsoft/vscode-cpptools/pull/5644) * Add threadExit and processExit logging flags for 'cppvsdbg'. [PR #5652](https://github.com/microsoft/vscode-cpptools/pull/5652) -* Add support to run cpp build tasks (Tasks: Run Build Task) [#3674](https://github.com/microsoft/vscode-cpptools/issues/3674) ### Bug Fixes * Fix IntelliSense when using "import_" in a variable name. [#5272](https://github.com/microsoft/vscode-cpptools/issues/5272) diff --git a/Extension/package.nls.json b/Extension/package.nls.json index 60567cbc1..673c2f91e 100644 --- a/Extension/package.nls.json +++ b/Extension/package.nls.json @@ -220,10 +220,10 @@ "c_cpp.debuggers.symbolLoadInfo.loadAll.description": "If true, symbols for all libs will be loaded, otherwise no solib symbols will be loaded. Default value is true.", "c_cpp.debuggers.symbolLoadInfo.exceptionList.description": "List of filenames (wildcards allowed) separated by semicolons ';'. Modifies behavior of LoadAll. If LoadAll is true then don't load symbols for libs that match any name in the list. Otherwise only load symbols for libs that match. Example: \"foo.so;bar.so\"", "c_cpp.debuggers.requireExactSource.description": "Optional flag to require current source code to match the pdb.", - "c_cpp.taskDefinitions.name.description": "The name of the task.", - "c_cpp.taskDefinitions.command.description": "The path to either a compiler or script that performs compilation.", - "c_cpp.taskDefinitions.args.description": "Additional arguments to pass to the compiler or compilation script.", - "c_cpp.taskDefinitions.options.description": "Additional command options.", + "c_cpp.taskDefinitions.name.description": "The name of the task", + "c_cpp.taskDefinitions.command.description": "The path to either a compiler or script that performs compilation", + "c_cpp.taskDefinitions.args.description": "Additional arguments to pass to the compiler or compilation script", + "c_cpp.taskDefinitions.options.description": "Additional command options", "c_cpp.taskDefinitions.options.cwd.description": "The current working directory of the executed program or script. If omitted Code's current workspace root is used.", - "c_cpp.taskDefinitions.detail.description": "Additional details of the task." + "c_cpp.taskDefinitions.detail.description": "Additional details of the task" }