From 2d0db0aa060b392ad89aad1e3fa01319d78bfca5 Mon Sep 17 00:00:00 2001 From: Colen Garoutte-Carson Date: Mon, 6 Dec 2021 17:02:25 -0800 Subject: [PATCH 01/15] Work in progress --- Extension/package.json | 426 +------ Extension/src/Debugger/attachToProcess.ts | 16 +- .../Debugger/debugAdapterDescriptorFactory.ts | 18 +- Extension/src/LanguageServer/extension.ts | 233 ++-- Extension/src/commands.ts | 180 +-- Extension/src/common.ts | 205 ++-- Extension/src/installationInformation.ts | 62 +- Extension/src/main.ts | 826 +++++++------ Extension/src/packageManager.ts | 1060 ++++++++--------- 9 files changed, 1344 insertions(+), 1682 deletions(-) diff --git a/Extension/package.json b/Extension/package.json index 6325529ba0..39bb78b125 100644 --- a/Extension/package.json +++ b/Extension/package.json @@ -11,7 +11,7 @@ }, "license": "SEE LICENSE IN LICENSE.txt", "engines": { - "vscode": "^1.60.0" + "vscode": "^1.61.0" }, "bugs": { "url": "https://github.com/Microsoft/vscode-cpptools/issues", @@ -45,7 +45,41 @@ "virtualWorkspaces": false }, "activationEvents": [ - "*" + "onLanguage:c", + "onLanguage:cpp", + "onLanguage:cuda-cpp", + "onCommand:extension.pickNativeProcess", + "onCommand:extension.pickRemoteNativeProcess", + "onCommand:C_Cpp.BuildAndDebugActiveFile", + "onCommand:C_Cpp.RestartIntelliSenseForFile", + "onCommand:C_Cpp.ConfigurationEditJSON", + "onCommand:C_Cpp.ConfigurationEditUI", + "onCommand:C_Cpp.ConfigurationSelect", + "onCommand:C_Cpp.ConfigurationProviderSelect", + "onCommand:C_Cpp.SwitchHeaderSource", + "onCommand:C_Cpp.EnableErrorSquiggles", + "onCommand:C_Cpp.DisableErrorSquiggles", + "onCommand:C_Cpp.ToggleIncludeFallback", + "onCommand:C_Cpp.ToggleDimInactiveRegions", + "onCommand:C_Cpp.ResetDatabase", + "onCommand:C_Cpp.TakeSurvey", + "onCommand:C_Cpp.LogDiagnostics", + "onCommand:C_Cpp.RescanWorkspace", + "onCommand:C_Cpp.VcpkgClipboardInstallSuggested", + "onCommand:C_Cpp.VcpkgOnlineHelpSuggested", + "onCommand:C_Cpp.GenerateEditorConfig", + "onCommand:C_Cpp.GoToNextDirectiveInGroup", + "onCommand:C_Cpp.GoToPrevDirectiveInGroup", + "onCommand:C_Cpp.CheckForCompiler", + "onCommand:C_Cpp.RunCodeAnalysisOnActiveFile", + "onCommand:C_Cpp.RunCodeAnalysisOnOpenFiles", + "onCommand:C_Cpp.RunCodeAnalysisOnAllFiles", + "onCommand:C_Cpp.ClearCodeAnalysisSquiggles", + "onDebugInitialConfigurations", + "onDebugResolve:cppdbg", + "onDebugResolve:cppvsdbg", + "workspaceContains:/.vscode/c_cpp_properties.json", + "onFileSystem:cpptools-schema" ], "main": "./dist/main", "contributes": { @@ -4385,391 +4419,5 @@ "path-parse": "^1.0.7", "axios": "^0.21.4", "set-value": "^4.0.1" - }, - "runtimeDependencies": [ - { - "description": "C/C++ language components (Linux / x86_64)", - "url": "https://go.microsoft.com/fwlink/?linkid=2175018", - "platforms": [ - "linux" - ], - "architectures": [ - "x64" - ], - "binaries": [ - "./bin/cpptools", - "./bin/cpptools-srv" - ], - "integrity": "2C657DD48E5C327242C912954315098F81329190C72CE4D4FCB228264BE3AA01" - }, - { - "description": "C/C++ language components (Linux / armhf)", - "url": "https://go.microsoft.com/fwlink/?linkid=2174710", - "platforms": [ - "linux" - ], - "architectures": [ - "arm" - ], - "binaries": [ - "./bin/cpptools", - "./bin/cpptools-srv" - ], - "integrity": "22E6BDD91BF0E8592D1101034AE0459E9B103947F246478932650E34C1FAE8C1" - }, - { - "description": "C/C++ language components (Linux / aarch64)", - "url": "https://go.microsoft.com/fwlink/?linkid=2174708", - "platforms": [ - "linux" - ], - "architectures": [ - "arm64" - ], - "binaries": [ - "./bin/cpptools", - "./bin/cpptools-srv" - ], - "integrity": "D43ECEC2DCCA9E62B3C3A03C404AC383E570717C4343A3D0C56BADA0991336CD" - }, - { - "description": "C/C++ language components (macOS / x86_64)", - "url": "https://go.microsoft.com/fwlink/?linkid=2175017", - "platforms": [ - "darwin" - ], - "architectures": [ - "x64" - ], - "binaries": [ - "./bin/cpptools", - "./bin/cpptools-srv" - ], - "integrity": "3409C9D435F97EBD2F1176124873A675C81A079842F41E6E75EC1A78F454535A" - }, - { - "description": "C/C++ language components (macOS / ARM64)", - "url": "https://go.microsoft.com/fwlink/?linkid=2174709", - "platforms": [ - "darwin" - ], - "architectures": [ - "arm64" - ], - "binaries": [ - "./bin/cpptools", - "./bin/cpptools-srv" - ], - "integrity": "3557666DB85407E8CF12BB2C807C83F3ABD55DF811075A91544CC98BC092B9E2" - }, - { - "description": "C/C++ language components (Windows)", - "url": "https://go.microsoft.com/fwlink/?linkid=2175016", - "platforms": [ - "win32" - ], - "architectures": [ - "x64", - "x86" - ], - "binaries": [ - "./bin/cpptools.exe", - "./bin/cpptools-srv.exe" - ], - "integrity": "40D2953E807B48AB05EDB865F48928B2E09C0C0A84834E4022D6BA6333159F3D" - }, - { - "description": "C/C++ language components (Windows ARM64)", - "url": "https://go.microsoft.com/fwlink/?linkid=2174707", - "platforms": [ - "win32" - ], - "architectures": [ - "arm64" - ], - "binaries": [ - "./bin/cpptools.exe", - "./bin/cpptools-srv.exe" - ], - "integrity": "040AC8D9BFD5648C283A567520A0B76871593C0594C5F9266CFB5F321BBE0DA8" - }, - { - "description": "Clang tools (Linux / x86_64)", - "url": "https://go.microsoft.com/fwlink/?LinkID=2167549", - "platforms": [ - "linux" - ], - "architectures": [ - "x64" - ], - "binaries": [ - "./LLVM/bin/clang-format", - "./LLVM/bin/clang-tidy" - ], - "integrity": "0B5F60E1D18B14FFF97EA436A080AC03D7A1B591A835E0F2B39C01C058375E36" - }, - { - "description": "Clang tools (Linux / armhf)", - "url": "https://go.microsoft.com/fwlink/?LinkID=2167551", - "platforms": [ - "linux" - ], - "architectures": [ - "arm" - ], - "binaries": [ - "./LLVM/bin/clang-format", - "./LLVM/bin/clang-tidy" - ], - "integrity": "80855487EE8E26E16F36A8E45A46366B6EA71AE7CFFB64022612019B014F0ED8" - }, - { - "description": "Clang tools (Linux / aarch64)", - "url": "https://go.microsoft.com/fwlink/?LinkID=2167656", - "platforms": [ - "linux" - ], - "architectures": [ - "arm64" - ], - "binaries": [ - "./LLVM/bin/clang-format", - "./LLVM/bin/clang-tidy" - ], - "integrity": "2B5839C2E26DAE6DE9FF555FD096C517C5AEB003297F6DEFEE5290AB73CD0CE6" - }, - { - "description": "Clang tools (macOS / x86_64)", - "url": "https://go.microsoft.com/fwlink/?LinkID=2167655", - "platforms": [ - "darwin" - ], - "architectures": [ - "x64" - ], - "binaries": [ - "./LLVM/bin/clang-format", - "./LLVM/bin/clang-tidy" - ], - "integrity": "DD9A702A8104D385357D5A192F47E0D8EC516FC6239C8E210C429881F32A21DF" - }, - { - "description": "Clang tools (macOS / ARM64)", - "url": "https://go.microsoft.com/fwlink/?LinkID=2167654", - "platforms": [ - "darwin" - ], - "architectures": [ - "arm64" - ], - "binaries": [ - "./LLVM/bin/clang-format", - "./LLVM/bin/clang-tidy" - ], - "integrity": "D5C827306C7AA94B3C2397E592199F1C68ADD4DB4BECF552B3C02CB280AC875B" - }, - { - "description": "Clang tools (Windows x86)", - "url": "https://go.microsoft.com/fwlink/?LinkID=2167552", - "platforms": [ - "win32" - ], - "architectures": [ - "x86" - ], - "binaries": [ - "./LLVM/bin/clang-format.exe", - "./LLVM/bin/clang-tidy.exe" - ], - "integrity": "66BAAC412988FE1E40CE6F94BDE64BB7A2FB7C4E2493EBDBE6B4F994604A3FBD" - }, - { - "description": "Clang tools (Windows x64)", - "url": "https://go.microsoft.com/fwlink/?LinkID=2167550", - "platforms": [ - "win32" - ], - "architectures": [ - "x64" - ], - "binaries": [ - "./LLVM/bin/clang-format.exe", - "./LLVM/bin/clang-tidy.exe" - ], - "integrity": "702AF7F679CB943D3D80C2E68FC7B5708ACAA227E84417F835AE9C6A7468808E" - }, - { - "description": "Clang tools (Windows arm64)", - "url": "https://go.microsoft.com/fwlink/?LinkID=2167548", - "platforms": [ - "win32" - ], - "architectures": [ - "arm64" - ], - "binaries": [ - "./LLVM/bin/clang-format.exe", - "./LLVM/bin/clang-tidy.exe" - ], - "integrity": "76032192FE82E8C51A4721E7C9660B3B5755BF75DAF47A71F844F561732A92F5" - }, - { - "description": "OpenDebugAD7 (Windows x86/x64)", - "url": "https://download.visualstudio.microsoft.com/download/pr/19b0fca0-b008-4b39-9163-6b7a59e50961/b6f4a97889ec460d5a7cb8e880c802ba/win-x86.zip", - "platforms": [ - "win32" - ], - "architectures": [ - "x86", - "x64" - ], - "binaries": [ - "./debugAdapters/bin/OpenDebugAD7.exe" - ], - "integrity": "6E3D9651FF1ACCFB90A5CEF0F4B5C3FEFB4B8D0D68EC1A9E662428C0558BB062" - }, - { - "description": "OpenDebugAD7 (Windows ARM64)", - "url": "https://download.visualstudio.microsoft.com/download/pr/19b0fca0-b008-4b39-9163-6b7a59e50961/10847664407c73081a2b1e77368d1b2e/win10-arm64.zip", - "platforms": [ - "win32" - ], - "architectures": [ - "arm64" - ], - "binaries": [ - "./debugAdapters/bin/OpenDebugAD7.exe" - ], - "integrity": "A583716260318ACA8DDD27E8CAC68A1D1D6F9435871720ABF55740BA7A58096A" - }, - { - "description": "OpenDebugAD7 (Linux x64)", - "url": "https://download.visualstudio.microsoft.com/download/pr/19b0fca0-b008-4b39-9163-6b7a59e50961/99f1a2287dcf76cc2ad85b800bba9c01/linux-x64.zip", - "platforms": [ - "linux" - ], - "architectures": [ - "x64" - ], - "binaries": [ - "./debugAdapters/bin/OpenDebugAD7" - ], - "integrity": "5746E5C1372ACC1CB86D599447FBD4E1F8AA6994590AE5FCC9B961BDD09183E9" - }, - { - "description": "OpenDebugAD7 (Linux ARM)", - "url": "https://download.visualstudio.microsoft.com/download/pr/19b0fca0-b008-4b39-9163-6b7a59e50961/ed287e8059e08c574952f5231ffbc1ba/linux-arm.zip", - "platforms": [ - "linux" - ], - "architectures": [ - "arm" - ], - "binaries": [ - "./debugAdapters/bin/OpenDebugAD7" - ], - "integrity": "7D6F99793D2824EE996A37357663BDAA6BE929092DD3CEB16C5A532820B0E51D" - }, - { - "description": "OpenDebugAD7 (Linux ARM64)", - "url": "https://download.visualstudio.microsoft.com/download/pr/19b0fca0-b008-4b39-9163-6b7a59e50961/b9dc0e0f12f33d0b88be942cb1ff5ebe/linux-arm64.zip", - "platforms": [ - "linux" - ], - "architectures": [ - "arm64" - ], - "binaries": [ - "./debugAdapters/bin/OpenDebugAD7" - ], - "integrity": "94BA61786551685D19130F0AE740F6A4EA4D2862B3364E08A53117773CFC1032" - }, - { - "description": "OpenDebugAD7 (Alpine Linux x64)", - "url": "https://download.visualstudio.microsoft.com/download/pr/19b0fca0-b008-4b39-9163-6b7a59e50961/f74cb83d6e43dfc2c30a9a0ec46d46b4/linux-musl-x64.zip", - "platforms": [ - "alpine-linux" - ], - "architectures": [ - "x64" - ], - "binaries": [ - "./debugAdapters/bin/OpenDebugAD7" - ], - "integrity": "5B0400B1F28E059CC74AEA02174661659C0FF89F4835E9947C9F853212A72984" - }, - { - "description": "OpenDebugAD7 (macOS x64)", - "url": "https://download.visualstudio.microsoft.com/download/pr/19b0fca0-b008-4b39-9163-6b7a59e50961/7ed17c1525fb70665716366891d2296a/osx-x64.zip", - "platforms": [ - "darwin" - ], - "architectures": [ - "x64", - "arm64" - ], - "binaries": [ - "./debugAdapters/bin/OpenDebugAD7" - ], - "integrity": "48C36077BD4BE44E2B62246CDD72F90FAAAE26E3D3199CDC980047F41E31B718" - }, - { - "description": "LLDB-MI (macOS Mojave and higher)", - "url": "https://go.microsoft.com/fwlink/?linkid=2154927", - "platforms": [ - "darwin" - ], - "versionRegex": "10\\.(1[0-3]|[0-9])(\\..*)*$", - "matchVersion": false, - "binaries": [ - "./debugAdapters/lldb-mi/bin/lldb-mi" - ], - "integrity": "FA76E76C7D8E5D5CD0CC8E68C6FB70A354750D596DF3CED36ABF78AAD5C562C0" - }, - { - "description": "LLDB 3.8.0 (macOS High Sierra and lower)", - "url": "https://go.microsoft.com/fwlink/?LinkID=817244", - "platforms": [ - "darwin" - ], - "versionRegex": "10\\.(1[0-3]|[0-9])(\\..*)*$", - "matchVersion": true, - "binaries": [ - "./debugAdapters/lldb/bin/debugserver", - "./debugAdapters/lldb/bin/lldb-mi", - "./debugAdapters/lldb/bin/lldb-argdumper", - "./debugAdapters/lldb/bin/lldb-launcher" - ], - "integrity": "D4ACCD43F562E42CE30879AC15ADF5FB6AA50656795DCE8F3AD32FB108BB3B7E" - }, - { - "description": "Visual Studio Windows Debugger", - "url": "https://go.microsoft.com/fwlink/?linkid=2169833", - "platforms": [ - "win32" - ], - "architectures": [ - "x64", - "x86" - ], - "binaries": [ - "./debugAdapters/vsdbg/bin/vsdbg.exe" - ], - "integrity": "0C36EB31D90EC6FE5BFBD02D62222A7FE8E5BD7D238D9DD086BAAEA66C74FF16" - }, - { - "description": "Visual Studio Windows ARM64 Debugger", - "url": "https://go.microsoft.com/fwlink/?linkid=2169834", - "platforms": [ - "win32" - ], - "architectures": [ - "arm64" - ], - "binaries": [ - "./debugAdapters/vsdbg/bin/vsdbg.exe" - ], - "integrity": "7DBD8F522420703AA85435A779CAC29B8226A8B92236BEF27AA41E84E4973458" - } - ] + } } \ No newline at end of file diff --git a/Extension/src/Debugger/attachToProcess.ts b/Extension/src/Debugger/attachToProcess.ts index 0d827c049e..d00cbe1697 100644 --- a/Extension/src/Debugger/attachToProcess.ts +++ b/Extension/src/Debugger/attachToProcess.ts @@ -26,11 +26,11 @@ export class AttachPicker { // We should not await on this function. public async ShowAttachEntries(): Promise { - if (!await util.isExtensionReady()) { - util.displayExtensionNotReadyPrompt(); - } else { + // if (!await util.isExtensionReady()) { + // util.displayExtensionNotReadyPrompt(); + // } else { return showQuickPick(() => this.attachItemsProvider.getAttachItems()); - } + // } } } @@ -42,9 +42,9 @@ export class RemoteAttachPicker { private _channel: vscode.OutputChannel; public async ShowAttachEntries(config: any): Promise { - if (!await util.isExtensionReady()) { - util.displayExtensionNotReadyPrompt(); - } else { + // if (!await util.isExtensionReady()) { + // util.displayExtensionNotReadyPrompt(); + // } else { this._channel.clear(); const pipeTransport: any = config ? config.pipeTransport : undefined; @@ -100,7 +100,7 @@ export class RemoteAttachPicker { } else { throw new Error(localize("process.not.selected", "Process not selected.")); } - } + // } } // Creates a string to run on the host machine which will execute a shell script on the remote machine to retrieve OS and processes diff --git a/Extension/src/Debugger/debugAdapterDescriptorFactory.ts b/Extension/src/Debugger/debugAdapterDescriptorFactory.ts index e67df8d789..6862ecb951 100644 --- a/Extension/src/Debugger/debugAdapterDescriptorFactory.ts +++ b/Extension/src/Debugger/debugAdapterDescriptorFactory.ts @@ -4,7 +4,7 @@ * ------------------------------------------------------------------------------------------ */ import * as vscode from "vscode"; -import * as util from '../common'; +//import * as util from '../common'; import * as path from 'path'; import * as os from 'os'; import * as nls from 'vscode-nls'; @@ -34,16 +34,16 @@ export class CppdbgDebugAdapterDescriptorFactory extends AbstractDebugAdapterDes } async createDebugAdapterDescriptor(session: vscode.DebugSession, executable?: vscode.DebugAdapterExecutable): Promise { - if (await util.isExtensionReady()) { + // if (await util.isExtensionReady()) { const adapter: string = "./debugAdapters/bin/OpenDebugAD7" + (os.platform() === 'win32' ? ".exe" : ""); const command: string = path.join(this.context.extensionPath, adapter); return new vscode.DebugAdapterExecutable(command, []); - } else { - throw new Error(util.extensionNotReadyString); - } + // } else { + // throw new Error(util.extensionNotReadyString); + // } } } @@ -59,14 +59,14 @@ export class CppvsdbgDebugAdapterDescriptorFactory extends AbstractDebugAdapterD vscode.window.showErrorMessage(localize("debugger.not.available", "Debugger type '{0}' is not avaliable for non-Windows machines.", "cppvsdbg")); return null; } else { - if (await util.isExtensionReady()) { + // if (await util.isExtensionReady()) { return new vscode.DebugAdapterExecutable( path.join(this.context.extensionPath, './debugAdapters/vsdbg/bin/vsdbg.exe'), ['--interpreter=vscode', '--extConfigDir=%USERPROFILE%\\.cppvsdbg\\extensions'] ); - } else { - throw new Error(util.extensionNotReadyString); - } + // } else { + // throw new Error(util.extensionNotReadyString); + // } } } } diff --git a/Extension/src/LanguageServer/extension.ts b/Extension/src/LanguageServer/extension.ts index 59b6e98143..8342d0da26 100644 --- a/Extension/src/LanguageServer/extension.ts +++ b/Extension/src/LanguageServer/extension.ts @@ -15,7 +15,8 @@ import { UI, getUI } from './ui'; import { Client, openFileVersions } from './client'; import { ClientCollection } from './clientCollection'; import { CppSettings, OtherSettings } from './settings'; -import { PersistentWorkspaceState, PersistentState } from './persistentState'; +//import { PersistentWorkspaceState, PersistentState } from './persistentState'; +import { PersistentState } from './persistentState'; import { getLanguageConfig } from './languageConfig'; import { getCustomConfigProviders } from './customProviders'; import { PlatformInformation } from '../platform'; @@ -23,7 +24,7 @@ import { Range } from 'vscode-languageclient'; import { ChildProcess, spawn } from 'child_process'; import { getTargetBuildInfo, BuildInfo } from '../githubAPI'; import { PackageVersion } from '../packageVersion'; -import { getTemporaryCommandRegistrarInstance } from '../commands'; +//import { getTemporaryCommandRegistrarInstance } from '../commands'; import * as rd from 'readline'; import * as yauzl from 'yauzl'; import { Readable, Writable } from 'stream'; @@ -46,9 +47,9 @@ let intervalTimer: NodeJS.Timer; let insiderUpdateEnabled: boolean = false; let insiderUpdateTimer: NodeJS.Timer; const insiderUpdateTimerInterval: number = 1000 * 60 * 60; -let realActivationOccurred: boolean = false; -let tempCommands: vscode.Disposable[] = []; -let activatedPreviously: PersistentWorkspaceState; +//let realActivationOccurred: boolean = false; +//let tempCommands: vscode.Disposable[] = []; +//let activatedPreviously: PersistentWorkspaceState; let buildInfoCache: BuildInfo | undefined; const cppInstallVsixStr: string = 'C/C++: Install vsix -- '; let taskProvider: vscode.Disposable; @@ -148,44 +149,63 @@ function isMissingIncludeDiagnostic(diagnostic: vscode.Diagnostic): boolean { return diagnostic.code === missingIncludeCode && diagnostic.source === 'C/C++'; } +function sendActivationTelemetry(): void { + const activateEvent: { [key: string]: string } = {}; + // Don't log telemetry for machineId if it's a special value used by the dev host: someValue.machineid + if (vscode.env.machineId !== "someValue.machineId") { + const machineIdPersistentState: PersistentState = new PersistentState("CPP.machineId", undefined); + if (!machineIdPersistentState.Value) { + activateEvent["newMachineId"] = vscode.env.machineId; + } else if (machineIdPersistentState.Value !== vscode.env.machineId) { + activateEvent["newMachineId"] = vscode.env.machineId; + activateEvent["oldMachineId"] = machineIdPersistentState.Value; + } + machineIdPersistentState.Value = vscode.env.machineId; + } + if (vscode.env.uiKind === vscode.UIKind.Web) { + activateEvent["WebUI"] = "1"; + } + telemetry.logLanguageServerEvent("Activate", activateEvent); +} + /** * activate: set up the extension for language services */ export async function activate(activationEventOccurred: boolean): Promise { - if (realActivationOccurred) { - return; // Occurs if multiple delayed commands occur before the real commands are registered. - } - - // Activate immediately if an activation event occurred in the previous workspace session. - // If onActivationEvent doesn't occur, it won't auto-activate next time. - activatedPreviously = new PersistentWorkspaceState("activatedPreviously", false); - if (activatedPreviously.Value) { - activatedPreviously.Value = false; - realActivation(); - } - - if (tempCommands.length === 0) { // Only needs to be added once. - tempCommands.push(vscode.workspace.onDidOpenTextDocument(onDidOpenTextDocument)); - } + // if (realActivationOccurred) { + // return; // Occurs if multiple delayed commands occur before the real commands are registered. + // } + + // // Activate immediately if an activation event occurred in the previous workspace session. + // // If onActivationEvent doesn't occur, it won't auto-activate next time. + // activatedPreviously = new PersistentWorkspaceState("activatedPreviously", false); + // if (activatedPreviously.Value) { + // activatedPreviously.Value = false; + // realActivation(); + // } + + //if (tempCommands.length === 0) { // Only needs to be added once. + // tempCommands.push(vscode.workspace.onDidOpenTextDocument(onDidOpenTextDocument)); + //} // handle "workspaceContains:/.vscode/c_cpp_properties.json" activation event. - let cppPropertiesExists: boolean = false; + //let cppPropertiesExists: boolean = false; if (vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length > 0) { for (let i: number = 0; i < vscode.workspace.workspaceFolders.length; ++i) { const config: string = path.join(vscode.workspace.workspaceFolders[i].uri.fsPath, ".vscode/c_cpp_properties.json"); if (await util.checkFileExists(config)) { - cppPropertiesExists = true; + //cppPropertiesExists = true; const doc: vscode.TextDocument = await vscode.workspace.openTextDocument(config); vscode.languages.setTextDocumentLanguage(doc, "jsonc"); } } } - // Check if an activation event has already occurred. - if (activationEventOccurred) { - onActivationEvent(); - return; - } + // // Check if an activation event has already occurred. + // if (activationEventOccurred) { + // onActivationEvent(); + // return; + // } taskProvider = vscode.tasks.registerTaskProvider(CppBuildTaskProvider.CppBuildScriptType, cppBuildTaskProvider); @@ -247,67 +267,48 @@ export async function activate(activationEventOccurred: boolean): Promise } }); - if (cppPropertiesExists) { - onActivationEvent(); - return; - } - - // handle "onLanguage:c", "onLanguage:cpp" and "onLanguage:cuda-cpp" activation events. - if (vscode.workspace.textDocuments !== undefined && vscode.workspace.textDocuments.length > 0) { - for (let i: number = 0; i < vscode.workspace.textDocuments.length; ++i) { - const document: vscode.TextDocument = vscode.workspace.textDocuments[i]; - if (document.uri.scheme === "file") { - if (document.languageId === "c" || document.languageId === "cpp" || document.languageId === "cuda-cpp") { - onActivationEvent(); - return; - } - } - } - } -} - -function onDidOpenTextDocument(document: vscode.TextDocument): void { - if (document.languageId === "c" || document.languageId === "cpp" || document.languageId === "cuda-cpp") { - onActivationEvent(); - } -} - -function onActivationEvent(): void { - if (tempCommands.length === 0) { - return; - } - - // Cancel all the temp commands that just look for activations. - tempCommands.forEach((command) => { - command.dispose(); - }); - tempCommands = []; - if (!realActivationOccurred) { - realActivation(); - } - activatedPreviously.Value = true; -} - -function sendActivationTelemetry(): void { - const activateEvent: { [key: string]: string } = {}; - // Don't log telemetry for machineId if it's a special value used by the dev host: someValue.machineid - if (vscode.env.machineId !== "someValue.machineId") { - const machineIdPersistentState: PersistentState = new PersistentState("CPP.machineId", undefined); - if (!machineIdPersistentState.Value) { - activateEvent["newMachineId"] = vscode.env.machineId; - } else if (machineIdPersistentState.Value !== vscode.env.machineId) { - activateEvent["newMachineId"] = vscode.env.machineId; - activateEvent["oldMachineId"] = machineIdPersistentState.Value; - } - machineIdPersistentState.Value = vscode.env.machineId; - } - if (vscode.env.uiKind === vscode.UIKind.Web) { - activateEvent["WebUI"] = "1"; - } - telemetry.logLanguageServerEvent("Activate", activateEvent); -} - -function realActivation(): void { + // if (cppPropertiesExists) { + // onActivationEvent(); + // return; + // } + + // // handle "onLanguage:c", "onLanguage:cpp" and "onLanguage:cuda-cpp" activation events. + // if (vscode.workspace.textDocuments !== undefined && vscode.workspace.textDocuments.length > 0) { + // for (let i: number = 0; i < vscode.workspace.textDocuments.length; ++i) { + // const document: vscode.TextDocument = vscode.workspace.textDocuments[i]; + // if (document.uri.scheme === "file") { + // if (document.languageId === "c" || document.languageId === "cpp" || document.languageId === "cuda-cpp") { + // onActivationEvent(); + // return; + // } + // } + // } + // } +//} + +// function onDidOpenTextDocument(document: vscode.TextDocument): void { +// if (document.languageId === "c" || document.languageId === "cpp" || document.languageId === "cuda-cpp") { +// onActivationEvent(); +// } +// } + +// function onActivationEvent(): void { +// if (tempCommands.length === 0) { +// return; +// } +// +// // Cancel all the temp commands that just look for activations. +// tempCommands.forEach((command) => { +// command.dispose(); +// }); +// tempCommands = []; +// if (!realActivationOccurred) { +// realActivation(); +// } +// activatedPreviously.Value = true; +// } + +//function realActivation(): void { if (new CppSettings((vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length > 0) ? vscode.workspace.workspaceFolders[0]?.uri : undefined).intelliSenseEngine === "Disabled") { throw new Error(intelliSenseDisabledError); } else { @@ -324,7 +325,7 @@ function realActivation(): void { } } - realActivationOccurred = true; + //realActivationOccurred = true; console.log("starting language server"); clients = new ClientCollection(); ui = getUI(); @@ -792,7 +793,7 @@ export function registerCommands(): void { } commandsRegistered = true; - getTemporaryCommandRegistrarInstance().clearTempCommands(); + //getTemporaryCommandRegistrarInstance().clearTempCommands(); disposables.push(vscode.commands.registerCommand('C_Cpp.SwitchHeaderSource', onSwitchHeaderSource)); disposables.push(vscode.commands.registerCommand('C_Cpp.ResetDatabase', onResetDatabase)); disposables.push(vscode.commands.registerCommand('C_Cpp.ConfigurationSelect', onSelectConfiguration)); @@ -834,11 +835,10 @@ export function registerCommands(): void { disposables.push(vscode.commands.registerCommand('cpptools.setActiveConfigName', onSetActiveConfigName)); disposables.push(vscode.commands.registerCommand('C_Cpp.RestartIntelliSenseForFile', onRestartIntelliSenseForFile)); - getTemporaryCommandRegistrarInstance().executeDelayedCommands(); + //getTemporaryCommandRegistrarInstance().executeDelayedCommands(); } function onRestartIntelliSenseForFile(): void { - onActivationEvent(); const activeEditor: vscode.TextEditor | undefined = vscode.window.activeTextEditor; if (!activeEditor || !activeEditor.document || activeEditor.document.uri.scheme !== "file" || (activeEditor.document.languageId !== "c" && activeEditor.document.languageId !== "cpp" && activeEditor.document.languageId !== "cuda-cpp")) { @@ -848,7 +848,6 @@ function onRestartIntelliSenseForFile(): void { } async function onSwitchHeaderSource(): Promise { - onActivationEvent(); const activeEditor: vscode.TextEditor | undefined = vscode.window.activeTextEditor; if (!activeEditor || !activeEditor.document) { return; @@ -912,12 +911,10 @@ async function selectClient(): Promise { } function onResetDatabase(): void { - onActivationEvent(); clients.ActiveClient.resetDatabase(); } function onSelectConfiguration(): void { - onActivationEvent(); if (!isFolderOpen()) { vscode.window.showInformationMessage(localize("configuration.select.first", 'Open a folder first to select a configuration')); } else { @@ -928,7 +925,6 @@ function onSelectConfiguration(): void { } function onSelectConfigurationProvider(): void { - onActivationEvent(); if (!isFolderOpen()) { vscode.window.showInformationMessage(localize("configuration.provider.select.first", 'Open a folder first to select a configuration provider')); } else { @@ -937,7 +933,6 @@ function onSelectConfigurationProvider(): void { } function onEditConfigurationJSON(viewColumn: vscode.ViewColumn = vscode.ViewColumn.Active): void { - onActivationEvent(); telemetry.logLanguageServerEvent("SettingsCommand", { "palette": "json" }, undefined); if (!isFolderOpen()) { vscode.window.showInformationMessage(localize('edit.configurations.open.first', 'Open a folder first to edit configurations')); @@ -947,7 +942,6 @@ function onEditConfigurationJSON(viewColumn: vscode.ViewColumn = vscode.ViewColu } function onEditConfigurationUI(viewColumn: vscode.ViewColumn = vscode.ViewColumn.Active): void { - onActivationEvent(); telemetry.logLanguageServerEvent("SettingsCommand", { "palette": "ui" }, undefined); if (!isFolderOpen()) { vscode.window.showInformationMessage(localize('edit.configurations.open.first', 'Open a folder first to edit configurations')); @@ -957,7 +951,6 @@ function onEditConfigurationUI(viewColumn: vscode.ViewColumn = vscode.ViewColumn } function onEditConfiguration(viewColumn: vscode.ViewColumn = vscode.ViewColumn.Active): void { - onActivationEvent(); if (!isFolderOpen()) { vscode.window.showInformationMessage(localize('edit.configurations.open.first', 'Open a folder first to edit configurations')); } else { @@ -966,7 +959,6 @@ function onEditConfiguration(viewColumn: vscode.ViewColumn = vscode.ViewColumn.A } function onGenerateEditorConfig(): void { - onActivationEvent(); if (!isFolderOpen()) { const settings: CppSettings = new CppSettings(); settings.generateEditorConfig(); @@ -979,25 +971,21 @@ function onGenerateEditorConfig(): void { } function onGoToNextDirectiveInGroup(): void { - onActivationEvent(); const client: Client = getActiveClient(); client.handleGoToDirectiveInGroup(true); } function onGoToPrevDirectiveInGroup(): void { - onActivationEvent(); const client: Client = getActiveClient(); client.handleGoToDirectiveInGroup(false); } function onCheckForCompiler(): void { - onActivationEvent(); const client: Client = getActiveClient(); client.handleCheckForCompiler(); } async function onRunCodeAnalysisOnActiveFile(): Promise { - onActivationEvent(); if (activeDocument !== "") { await vscode.commands.executeCommand("workbench.action.files.saveAll"); getActiveClient().handleRunCodeAnalysisOnActiveFile(); @@ -1005,7 +993,6 @@ async function onRunCodeAnalysisOnActiveFile(): Promise { } async function onRunCodeAnalysisOnOpenFiles(): Promise { - onActivationEvent(); if (openFileVersions.size > 0) { await vscode.commands.executeCommand("workbench.action.files.saveAll"); getActiveClient().handleRunCodeAnalysisOnOpenFiles(); @@ -1013,13 +1000,11 @@ async function onRunCodeAnalysisOnOpenFiles(): Promise { } async function onRunCodeAnalysisOnAllFiles(): Promise { - onActivationEvent(); await vscode.commands.executeCommand("workbench.action.files.saveAll"); getActiveClient().handleRunCodeAnalysisOnAllFiles(); } async function onClearCodeAnalysisSquiggles(): Promise { - onActivationEvent(); getActiveClient().handleClearCodeAnalysisSquiggles(); } @@ -1034,70 +1019,58 @@ function onAddToIncludePath(path: string): void { } function onEnableSquiggles(): void { - onActivationEvent(); // This only applies to the active client. const settings: CppSettings = new CppSettings(clients.ActiveClient.RootUri); settings.update("errorSquiggles", "Enabled"); } function onDisableSquiggles(): void { - onActivationEvent(); // This only applies to the active client. const settings: CppSettings = new CppSettings(clients.ActiveClient.RootUri); settings.update("errorSquiggles", "Disabled"); } function onToggleIncludeFallback(): void { - onActivationEvent(); // This only applies to the active client. const settings: CppSettings = new CppSettings(clients.ActiveClient.RootUri); settings.toggleSetting("intelliSenseEngineFallback", "Enabled", "Disabled"); } function onToggleDimInactiveRegions(): void { - onActivationEvent(); // This only applies to the active client. const settings: CppSettings = new CppSettings(clients.ActiveClient.RootUri); settings.update("dimInactiveRegions", !settings.dimInactiveRegions); } function onPauseParsing(): void { - onActivationEvent(); clients.ActiveClient.pauseParsing(); } function onResumeParsing(): void { - onActivationEvent(); clients.ActiveClient.resumeParsing(); } function onPauseCodeAnalysis(): void { - onActivationEvent(); clients.ActiveClient.PauseCodeAnalysis(); } function onResumeCodeAnalysis(): void { - onActivationEvent(); clients.ActiveClient.ResumeCodeAnalysis(); } function onCancelCodeAnalysis(): void { - onActivationEvent(); clients.ActiveClient.CancelCodeAnalysis(); } function onShowParsingCommands(): void { - onActivationEvent(); clients.ActiveClient.handleShowParsingCommands(); } function onShowCodeAnalysisCommands(): void { - onActivationEvent(); clients.ActiveClient.handleShowCodeAnalysisCommands(); } function onShowReferencesProgress(): void { - onActivationEvent(); clients.ActiveClient.handleReferencesIcon(); } @@ -1108,7 +1081,6 @@ function onToggleRefGroupView(): void { } function onTakeSurvey(): void { - onActivationEvent(); telemetry.logLanguageServerEvent("onTakeSurvey"); const uri: vscode.Uri = vscode.Uri.parse(`https://www.research.net/r/VBVV6C6?o=${os.platform()}&m=${vscode.env.machineId}`); vscode.commands.executeCommand('vscode.open', uri); @@ -1121,7 +1093,6 @@ function onVcpkgOnlineHelpSuggested(dummy?: any): void { } async function onVcpkgClipboardInstallSuggested(ports?: string[]): Promise { - onActivationEvent(); let source: string; if (ports && ports.length) { source = 'CodeAction'; @@ -1189,12 +1160,10 @@ function onGetActiveConfigCustomVariable(variableName: string): Thenable } function onLogDiagnostics(): void { - onActivationEvent(); clients.ActiveClient.logDiagnostics(); } function onRescanWorkspace(): void { - onActivationEvent(); clients.ActiveClient.rescanFolder(); } @@ -1346,9 +1315,9 @@ function handleMacCrashFileRead(err: NodeJS.ErrnoException | undefined | null, d } export function deactivate(): Thenable { - if (!realActivationOccurred) { - return Promise.resolve(); - } + // if (!realActivationOccurred) { + // return Promise.resolve(); + // } clients.timeTelemetryCollector.clear(); console.log("deactivating extension"); telemetry.logLanguageServerEvent("LanguageServerShutdown"); @@ -1371,15 +1340,15 @@ export function isFolderOpen(): boolean { } export function getClients(): ClientCollection { - if (!realActivationOccurred) { - realActivation(); - } + // if (!realActivationOccurred) { + // realActivation(); + // } return clients; } export function getActiveClient(): Client { - if (!realActivationOccurred) { - realActivation(); - } + // if (!realActivationOccurred) { + // realActivation(); + // } return clients.ActiveClient; } diff --git a/Extension/src/commands.ts b/Extension/src/commands.ts index bfce15c5f9..03d25c48a5 100644 --- a/Extension/src/commands.ts +++ b/Extension/src/commands.ts @@ -1,104 +1,104 @@ -/* -------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All Rights Reserved. - * See 'LICENSE' in the project root for license information. - * ------------------------------------------------------------------------------------------ */ -'use strict'; +// /* -------------------------------------------------------------------------------------------- +// * Copyright (c) Microsoft Corporation. All Rights Reserved. +// * See 'LICENSE' in the project root for license information. +// * ------------------------------------------------------------------------------------------ */ +// 'use strict'; -import * as vscode from 'vscode'; -import * as LanguageServer from './LanguageServer/extension'; -import * as util from './common'; -import * as nls from 'vscode-nls'; +// import * as vscode from 'vscode'; +// import * as LanguageServer from './LanguageServer/extension'; +// import * as util from './common'; +// import * as nls from 'vscode-nls'; -nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })(); -const localize: nls.LocalizeFunc = nls.loadMessageBundle(); +// nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })(); +// const localize: nls.LocalizeFunc = nls.loadMessageBundle(); -class TemporaryCommandRegistrar { - // Used to save/re-execute commands used before the extension has activated (e.g. delayed by dependency downloading). - private delayedCommandsToExecute: Set; - private tempCommands: vscode.Disposable[]; // Need to save this to unregister/dispose the temporary commands. - private isLanguageServerDisabled: boolean = false; - private isActivationReady: boolean = false; +// class TemporaryCommandRegistrar { +// // Used to save/re-execute commands used before the extension has activated (e.g. delayed by dependency downloading). +// private delayedCommandsToExecute: Set; +// private tempCommands: vscode.Disposable[]; // Need to save this to unregister/dispose the temporary commands. +// private isLanguageServerDisabled: boolean = false; +// private isActivationReady: boolean = false; - private commandsToRegister: string[] = [ - "C_Cpp.ConfigurationEditJSON", - "C_Cpp.ConfigurationEditUI", - "C_Cpp.ConfigurationSelect", - "C_Cpp.ConfigurationProviderSelect", - "C_Cpp.SwitchHeaderSource", - "C_Cpp.EnableErrorSquiggles", - "C_Cpp.DisableErrorSquiggles", - "C_Cpp.ToggleIncludeFallback", - "C_Cpp.ToggleDimInactiveRegions", - "C_Cpp.ResetDatabase", - "C_Cpp.TakeSurvey", - "C_Cpp.LogDiagnostics", - "C_Cpp.RescanWorkspace", - "C_Cpp.GenerateEditorConfig", - "C_Cpp.VcpkgClipboardInstallSuggested", - "C_Cpp.VcpkgOnlineHelpSuggested", - "C_Cpp.CheckForCompiler", - "C_Cpp.RunCodeAnalysisOnActiveFile", - "C_Cpp.RunCodeAnalysisOnOpenFiles", - "C_Cpp.RunCodeAnalysisOnAllFiles", - "C_Cpp.ClearCodeAnalysisSquiggles" - ]; +// private commandsToRegister: string[] = [ +// "C_Cpp.ConfigurationEditJSON", +// "C_Cpp.ConfigurationEditUI", +// "C_Cpp.ConfigurationSelect", +// "C_Cpp.ConfigurationProviderSelect", +// "C_Cpp.SwitchHeaderSource", +// "C_Cpp.EnableErrorSquiggles", +// "C_Cpp.DisableErrorSquiggles", +// "C_Cpp.ToggleIncludeFallback", +// "C_Cpp.ToggleDimInactiveRegions", +// "C_Cpp.ResetDatabase", +// "C_Cpp.TakeSurvey", +// "C_Cpp.LogDiagnostics", +// "C_Cpp.RescanWorkspace", +// "C_Cpp.GenerateEditorConfig", +// "C_Cpp.VcpkgClipboardInstallSuggested", +// "C_Cpp.VcpkgOnlineHelpSuggested", +// "C_Cpp.CheckForCompiler", +// "C_Cpp.RunCodeAnalysisOnActiveFile", +// "C_Cpp.RunCodeAnalysisOnOpenFiles", +// "C_Cpp.RunCodeAnalysisOnAllFiles", +// "C_Cpp.ClearCodeAnalysisSquiggles" +// ]; - constructor() { - this.tempCommands = []; - this.delayedCommandsToExecute = new Set(); +// constructor() { +// this.tempCommands = []; +// this.delayedCommandsToExecute = new Set(); - // Add temp commands that invoke the real commands after download/install is complete (preventing an error message) - if (util.extensionContext) { - this.commandsToRegister.forEach(command => { - this.registerTempCommand(command); - }); - } - } +// // Add temp commands that invoke the real commands after download/install is complete (preventing an error message) +// if (util.extensionContext) { +// this.commandsToRegister.forEach(command => { +// this.registerTempCommand(command); +// }); +// } +// } - public registerTempCommand(command: string): void { - this.tempCommands.push(vscode.commands.registerCommand(command, () => { - if (this.isLanguageServerDisabled) { - vscode.window.showInformationMessage(localize("command.disabled", 'This command is disabled because "{0}" is set to "{1}".', "C_Cpp.intelliSenseEngine", "Disabled")); - return; - } - this.delayedCommandsToExecute.add(command); - if (this.isActivationReady) { - LanguageServer.activate(true); - } - })); - } +// public registerTempCommand(command: string): void { +// this.tempCommands.push(vscode.commands.registerCommand(command, () => { +// if (this.isLanguageServerDisabled) { +// vscode.window.showInformationMessage(localize("command.disabled", 'This command is disabled because "{0}" is set to "{1}".', "C_Cpp.intelliSenseEngine", "Disabled")); +// return; +// } +// this.delayedCommandsToExecute.add(command); +// if (this.isActivationReady) { +// LanguageServer.activate(true); +// } +// })); +// } - public disableLanguageServer(): void { - this.isLanguageServerDisabled = true; - } +// public disableLanguageServer(): void { +// this.isLanguageServerDisabled = true; +// } - public activateLanguageServer(): void { - // Main activation code. - LanguageServer.activate(this.delayedCommandsToExecute.size > 0); - this.isActivationReady = true; - } +// public activateLanguageServer(): void { +// // Main activation code. +// LanguageServer.activate(this.delayedCommandsToExecute.size > 0); +// this.isActivationReady = true; +// } - public clearTempCommands(): void { - this.tempCommands.forEach((command) => { - command.dispose(); - }); - this.tempCommands = []; - } +// public clearTempCommands(): void { +// this.tempCommands.forEach((command) => { +// command.dispose(); +// }); +// this.tempCommands = []; +// } - public executeDelayedCommands(): void { - this.delayedCommandsToExecute.forEach((command) => { - vscode.commands.executeCommand(command); - }); - this.delayedCommandsToExecute.clear(); - } -} +// public executeDelayedCommands(): void { +// this.delayedCommandsToExecute.forEach((command) => { +// vscode.commands.executeCommand(command); +// }); +// this.delayedCommandsToExecute.clear(); +// } +// } -let tempCommandRegistrar: TemporaryCommandRegistrar; +// // let tempCommandRegistrar: TemporaryCommandRegistrar; -export function initializeTemporaryCommandRegistrar(): void { - tempCommandRegistrar = new TemporaryCommandRegistrar(); -} +// // export function initializeTemporaryCommandRegistrar(): void { +// // tempCommandRegistrar = new TemporaryCommandRegistrar(); +// // } -export function getTemporaryCommandRegistrarInstance(): TemporaryCommandRegistrar { - return tempCommandRegistrar; -} +// // export function getTemporaryCommandRegistrarInstance(): TemporaryCommandRegistrar { +// // return tempCommandRegistrar; +// // } diff --git a/Extension/src/common.ts b/Extension/src/common.ts index 091d54d997..50d8beb4f0 100644 --- a/Extension/src/common.ts +++ b/Extension/src/common.ts @@ -20,7 +20,7 @@ import { ClientRequest, OutgoingHttpHeaders } from 'http'; import { lookupString } from './nativeStrings'; import * as nls from 'vscode-nls'; import { Readable } from 'stream'; -import { PackageManager, IPackage } from './packageManager'; +//import { PackageManager, IPackage } from './packageManager'; import * as jsonc from 'comment-json'; nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })(); @@ -174,12 +174,12 @@ export function isHeader(uri: vscode.Uri): boolean { return !ext || ext.startsWith(".h") || ext.startsWith(".H"); } -// Extension is ready if install.lock exists and debugAdapters folder exist. -export async function isExtensionReady(): Promise { - const doesInstallLockFileExist: boolean = await checkInstallLockFile(); - - return doesInstallLockFileExist; -} +// // Extension is ready if install.lock exists and debugAdapters folder exist. +// export async function isExtensionReady(): Promise { +// const doesInstallLockFileExist: boolean = await checkInstallLockFile(); +// +// return doesInstallLockFileExist; +// } let isExtensionNotReadyPromptDisplayed: boolean = false; export const extensionNotReadyString: string = localize("extension.not.ready", 'The C/C++ extension is still installing. See the output window for more information.'); @@ -425,19 +425,19 @@ export function getHttpsProxyAgent(): HttpsProxyAgent | undefined { return new HttpsProxyAgent(proxyOptions); } -export interface InstallLockContents { - platform: string; - architecture: string; -}; +// export interface InstallLockContents { +// platform: string; +// architecture: string; +// }; -export function touchInstallLockFile(info: PlatformInformation): Promise { - const installLockObject: InstallLockContents = { - platform: info.platform, - architecture: info.architecture - }; - const content: string = JSON.stringify(installLockObject); - return writeFileText(getInstallLockPath(), content); -} +// export function touchInstallLockFile(info: PlatformInformation): Promise { +// const installLockObject: InstallLockContents = { +// platform: info.platform, +// architecture: info.architecture +// }; +// const content: string = JSON.stringify(installLockObject); +// return writeFileText(getInstallLockPath(), content); +// } export function touchExtensionFolder(): Promise { return new Promise((resolve, reject) => { @@ -529,83 +529,83 @@ export function readDir(dirPath: string): Promise { }); } -/** Test whether the lock file exists.*/ -export function checkInstallLockFile(): Promise { - return checkFileExists(getInstallLockPath()); -} - -/** Check if the core binaries exists in extension's installation folder */ -export async function checkInstallBinariesExist(): Promise { - if (!checkInstallLockFile()) { - return false; - } - let installBinariesExist: boolean = true; - const info: PlatformInformation = await PlatformInformation.GetPlatformInformation(); - const packageManager: PackageManager = new PackageManager(info); - const packages: Promise = packageManager.GetPackages(); - for (const pkg of await packages) { - if (pkg.binaries) { - await Promise.all(pkg.binaries.map(async (file: string) => { - if (!await checkFileExists(file)) { - installBinariesExist = false; - const fileBase: string = path.basename(file); - console.log(`Extension file ${fileBase} is missing.`); - Telemetry.logLanguageServerEvent("missingBinary", { "source": `${fileBase}` }); - } - })); - } - } - return installBinariesExist; -} - -/** Check if the core Json files exists in extension's installation folder */ -export async function checkInstallJsonsExist(): Promise { - let installJsonsExist: boolean = true; - const jsonFiles: string[] = [ - "bin/common.json", - "bin/linux.clang.arm.json", - "bin/linux.clang.arm64.json", - "bin/linux.clang.x64.json", - "bin/linux.clang.x86.json", - "bin/linux.gcc.arm.json", - "bin/linux.gcc.arm64.json", - "bin/linux.gcc.x64.json", - "bin/linux.gcc.x86.json", - "bin/macos.clang.arm.json", - "bin/macos.clang.arm64.json", - "bin/macos.clang.x64.json", - "bin/macos.clang.x86.json", - "bin/macos.gcc.arm.json", - "bin/macos.gcc.arm64.json", - "bin/macos.gcc.x64.json", - "bin/macos.gcc.x86.json", - "bin/windows.clang.arm.json", - "bin/windows.clang.arm64.json", - "bin/windows.clang.x64.json", - "bin/windows.clang.x86.json", - "bin/windows.gcc.arm.json", - "bin/windows.gcc.arm64.json", - "bin/windows.gcc.x64.json", - "bin/windows.gcc.x86.json", - "bin/windows.msvc.arm.json", - "bin/windows.msvc.arm64.json", - "bin/windows.msvc.x64.json", - "bin/windows.msvc.x86.json", - "debugAdapters/bin/cppdbg.ad7Engine.json" - ]; - await Promise.all(jsonFiles.map(async (file) => { - if (!await checkFileExists(path.join(extensionPath, file))) { - installJsonsExist = false; - console.log(`Extension file ${file} is missing.`); - Telemetry.logLanguageServerEvent("missingJson", { "source": `${file}` }); - } - })); - return installJsonsExist; -} - -export async function removeInstallLockFile(): Promise { - await unlinkAsync(path.join(extensionPath, "install.lock")); -} +// /** Test whether the lock file exists.*/ +// export function checkInstallLockFile(): Promise { +// return checkFileExists(getInstallLockPath()); +// } + +// /** Check if the core binaries exists in extension's installation folder */ +// export async function checkInstallBinariesExist(): Promise { +// if (!checkInstallLockFile()) { +// return false; +// } +// let installBinariesExist: boolean = true; +// const info: PlatformInformation = await PlatformInformation.GetPlatformInformation(); +// const packageManager: PackageManager = new PackageManager(info); +// const packages: Promise = packageManager.GetPackages(); +// for (const pkg of await packages) { +// if (pkg.binaries) { +// await Promise.all(pkg.binaries.map(async (file: string) => { +// if (!await checkFileExists(file)) { +// installBinariesExist = false; +// const fileBase: string = path.basename(file); +// console.log(`Extension file ${fileBase} is missing.`); +// Telemetry.logLanguageServerEvent("missingBinary", { "source": `${fileBase}` }); +// } +// })); +// } +// } +// return installBinariesExist; +// } + +// /** Check if the core Json files exists in extension's installation folder */ +// export async function checkInstallJsonsExist(): Promise { +// let installJsonsExist: boolean = true; +// const jsonFiles: string[] = [ +// "bin/common.json", +// "bin/linux.clang.arm.json", +// "bin/linux.clang.arm64.json", +// "bin/linux.clang.x64.json", +// "bin/linux.clang.x86.json", +// "bin/linux.gcc.arm.json", +// "bin/linux.gcc.arm64.json", +// "bin/linux.gcc.x64.json", +// "bin/linux.gcc.x86.json", +// "bin/macos.clang.arm.json", +// "bin/macos.clang.arm64.json", +// "bin/macos.clang.x64.json", +// "bin/macos.clang.x86.json", +// "bin/macos.gcc.arm.json", +// "bin/macos.gcc.arm64.json", +// "bin/macos.gcc.x64.json", +// "bin/macos.gcc.x86.json", +// "bin/windows.clang.arm.json", +// "bin/windows.clang.arm64.json", +// "bin/windows.clang.x64.json", +// "bin/windows.clang.x86.json", +// "bin/windows.gcc.arm.json", +// "bin/windows.gcc.arm64.json", +// "bin/windows.gcc.x64.json", +// "bin/windows.gcc.x86.json", +// "bin/windows.msvc.arm.json", +// "bin/windows.msvc.arm64.json", +// "bin/windows.msvc.x64.json", +// "bin/windows.msvc.x86.json", +// "debugAdapters/bin/cppdbg.ad7Engine.json" +// ]; +// await Promise.all(jsonFiles.map(async (file) => { +// if (!await checkFileExists(path.join(extensionPath, file))) { +// installJsonsExist = false; +// console.log(`Extension file ${file} is missing.`); +// Telemetry.logLanguageServerEvent("missingJson", { "source": `${file}` }); +// } +// })); +// return installJsonsExist; +// } + +// export async function removeInstallLockFile(): Promise { +// await unlinkAsync(path.join(extensionPath, "install.lock")); +// } /** Reads the content of a text file */ export function readFileText(filePath: string, encoding: string = "utf8"): Promise { @@ -661,10 +661,10 @@ export function deleteFile(filePath: string): Promise { }); } -// Get the path of the lock file. This is used to indicate that the platform-specific dependencies have been downloaded. -export function getInstallLockPath(): string { - return getExtensionFilePath("install.lock"); -} +// // Get the path of the lock file. This is used to indicate that the platform-specific dependencies have been downloaded. +// export function getInstallLockPath(): string { +// return getExtensionFilePath("install.lock"); +// } export function getReadmeMessage(): string { const readmePath: string = getExtensionFilePath("README.md"); @@ -1300,11 +1300,6 @@ export function isCodespaces(): boolean { return !!process.env["CODESPACES"]; } -export async function checkCuda(): Promise { - const langs: string[] = await vscode.languages.getLanguages(); - supportCuda = langs.findIndex((s) => s === "cuda-cpp") !== -1; -} - // Sequentially Resolve Promises. export function sequentialResolve(items: T[], promiseBuilder: (item: T) => Promise): Promise { return items.reduce(async (previousPromise, nextItem) => { diff --git a/Extension/src/installationInformation.ts b/Extension/src/installationInformation.ts index 42ab61a5ec..0a3244bdfe 100644 --- a/Extension/src/installationInformation.ts +++ b/Extension/src/installationInformation.ts @@ -1,38 +1,38 @@ -/* -------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All Rights Reserved. - * See 'LICENSE' in the project root for license information. - * ------------------------------------------------------------------------------------------ */ +// /* -------------------------------------------------------------------------------------------- +// * Copyright (c) Microsoft Corporation. All Rights Reserved. +// * See 'LICENSE' in the project root for license information. +// * ------------------------------------------------------------------------------------------ */ -export enum InstallationType { - Online, - Offline -} +// export enum InstallationType { +// Online, +// Offline +// } -export class InstallationInformation { - stage?: string; - type?: InstallationType; - hasError: boolean; - telemetryProperties: { [key: string]: string }; +// export class InstallationInformation { +// stage?: string; +// type?: InstallationType; +// hasError: boolean; +// telemetryProperties: { [key: string]: string }; - constructor() { - this.hasError = false; - this.telemetryProperties = {}; - } -} +// constructor() { +// this.hasError = false; +// this.telemetryProperties = {}; +// } +// } -let installBlob: InstallationInformation; +// let installBlob: InstallationInformation; -export function getInstallationInformation(): InstallationInformation { - if (!installBlob) { - installBlob = new InstallationInformation(); - } - return installBlob; -} +// export function getInstallationInformation(): InstallationInformation { +// if (!installBlob) { +// installBlob = new InstallationInformation(); +// } +// return installBlob; +// } -export function setInstallationStage(stage: string): void { - getInstallationInformation().stage = stage; -} +// export function setInstallationStage(stage: string): void { +// getInstallationInformation().stage = stage; +// } -export function setInstallationType(type: InstallationType): void { - getInstallationInformation().type = type; -} +// export function setInstallationType(type: InstallationType): void { +// getInstallationInformation().type = type; +// } diff --git a/Extension/src/main.ts b/Extension/src/main.ts index 87566a8797..78549bceae 100644 --- a/Extension/src/main.ts +++ b/Extension/src/main.ts @@ -5,7 +5,7 @@ 'use strict'; import * as DebuggerExtension from './Debugger/extension'; -import * as fs from 'fs'; +//import * as fs from 'fs'; import * as LanguageServer from './LanguageServer/extension'; import * as os from 'os'; import * as path from 'path'; @@ -13,17 +13,19 @@ import * as Telemetry from './telemetry'; import * as util from './common'; import * as vscode from 'vscode'; import * as nls from 'vscode-nls'; -import { PersistentState } from './LanguageServer/persistentState'; +//import { PersistentState } from './LanguageServer/persistentState'; import { CppToolsApi, CppToolsExtension } from 'vscode-cpptools'; -import { getTemporaryCommandRegistrarInstance, initializeTemporaryCommandRegistrar } from './commands'; -import { PlatformInformation, GetOSName } from './platform'; -import { PackageManager, PackageManagerError, IPackage, VersionsMatch, ArchitecturesMatch, PlatformsMatch } from './packageManager'; -import { getInstallationInformation, InstallationInformation, setInstallationStage, setInstallationType, InstallationType } from './installationInformation'; -import { Logger, getOutputChannelLogger, showOutputChannel } from './logger'; -import { CppTools1, NullCppTools } from './cppTools1'; +//import { getTemporaryCommandRegistrarInstance, initializeTemporaryCommandRegistrar } from './commands'; +//import { PlatformInformation, GetOSName } from './platform'; +import { PlatformInformation } from './platform'; +//import { PackageManager, PackageManagerError, IPackage, VersionsMatch, ArchitecturesMatch, PlatformsMatch } from './packageManager'; +//import { getInstallationInformation, InstallationInformation, setInstallationStage, setInstallationType, InstallationType } from './installationInformation'; +//import { Logger, getOutputChannelLogger, showOutputChannel } from './logger'; +//import { CppTools1, NullCppTools } from './cppTools1'; +import { CppTools1 } from './cppTools1'; import { CppSettings } from './LanguageServer/settings'; -import { vsixNameForPlatform, releaseDownloadUrl } from './githubAPI'; +//import { vsixNameForPlatform, releaseDownloadUrl } from './githubAPI'; nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })(); const localize: nls.LocalizeFunc = nls.loadMessageBundle(); @@ -34,22 +36,20 @@ let reloadMessageShown: boolean = false; const disposables: vscode.Disposable[] = []; export async function activate(context: vscode.ExtensionContext): Promise { - await util.checkCuda(); - - let errMsg: string = ""; - const arch: string = PlatformInformation.GetArchitecture(); - if (arch !== 'x64' && (process.platform !== 'win32' || (arch !== 'x86' && arch !== 'arm64')) && ((process.platform === 'win32' || process.platform === 'darwin') || (arch !== 'arm' && arch !== 'arm64')) && (process.platform !== 'darwin' || arch !== 'arm64')) { - errMsg = localize("architecture.not.supported", "Architecture {0} is not supported. ", String(arch)); - } else if (process.platform === 'linux' && await util.checkDirectoryExists('/etc/alpine-release')) { - errMsg = localize("apline.containers.not.supported", "Alpine containers are not supported."); - } - if (errMsg) { - vscode.window.showErrorMessage(errMsg); - return new NullCppTools(); - } + // let errMsg: string = ""; + // const arch: string = PlatformInformation.GetArchitecture(); + // if (arch !== 'x64' && (process.platform !== 'win32' || (arch !== 'x86' && arch !== 'arm64')) && ((process.platform === 'win32' || process.platform === 'darwin') || (arch !== 'arm' && arch !== 'arm64')) && (process.platform !== 'darwin' || arch !== 'arm64')) { + // errMsg = localize("architecture.not.supported", "Architecture {0} is not supported. ", String(arch)); + // } else if (process.platform === 'linux' && await util.checkDirectoryExists('/etc/alpine-release')) { + // errMsg = localize("apline.containers.not.supported", "Alpine containers are not supported."); + // } + // if (errMsg) { + // vscode.window.showErrorMessage(errMsg); + // return new NullCppTools(); + // } util.setExtensionContext(context); - initializeTemporaryCommandRegistrar(); + //initializeTemporaryCommandRegistrar(); Telemetry.activate(); util.setProgress(0); @@ -73,63 +73,95 @@ export async function activate(context: vscode.ExtensionContext): PromiseJSON.parse(fileContents); - } catch (error) { - // If the contents of install.lock are corrupted, treat as if it's empty. - } + //await processRuntimeDependencies(); + //setInstallationStage('getPlatformInfo'); + const info: PlatformInformation = await PlatformInformation.GetPlatformInformation(); + //setInstallationStage('makeBinariesExecutable'); + await makeBinariesExecutable(info); + //setInstallationStage('postInstall'); + const installSuccess: boolean = sendTelemetry(info); + + // If there is a download failure, we shouldn't continue activating the extension in some broken state. + if (!installSuccess) { + throw new Error(localize("failed.installing.dependencies", "Failed installing dependencies")); } + // Notify users if debugging may not be supported on their OS. + util.checkDistro(info); - // Check the main binaries files to declare if the extension has been installed successfully. - if (process.platform !== installedPlatformAndArchitecture.platform - || (arch !== installedPlatformAndArchitecture.architecture - && !(process.platform === "win32" - // On x64 Windows, allow x86 binaries. - && ((arch === "x64" && installedPlatformAndArchitecture.architecture === "x86") - // On arm64 Windows, allow x86 or x64 binaries. - || (arch === "arm64" && ((installedPlatformAndArchitecture.architecture === "x86") || (installedPlatformAndArchitecture.architecture === "x64"))))) - // On arm64 macOS, allow x64 binaries. - && !(process.platform === "darwin" && arch === "arm64" && installedPlatformAndArchitecture.architecture === "x64"))) { - // Check if the correct offline/insiders vsix is installed on the correct platform. - const platformInfo: PlatformInformation = await PlatformInformation.GetPlatformInformation(); - const vsixName: string = vsixNameForPlatform(platformInfo); - const downloadLink: string = localize("download.button", "Go to Download Page"); - errMsg = localize("native.binaries.not.supported", "This {0} {1} version of the extension is incompatible with your OS. Please download and install the \"{2}\" version of the extension.", GetOSName(installedPlatformAndArchitecture.platform), installedPlatformAndArchitecture.architecture, vsixName); - vscode.window.showErrorMessage(errMsg, downloadLink).then(async (selection) => { - if (selection === downloadLink) { - vscode.env.openExternal(vscode.Uri.parse(releaseDownloadUrl)); - } - }); - } else if (!(await util.checkInstallBinariesExist())) { - errMsg = localize("extension.installation.failed", "The C/C++ extension failed to install successfully. You will need to repair or reinstall the extension for C/C++ language features to function properly."); - const reload: string = localize("remove.extension", "Attempt to Repair"); - vscode.window.showErrorMessage(errMsg, reload).then(async (value?: string) => { - if (value === reload) { - await util.removeInstallLockFile(); - vscode.commands.executeCommand("workbench.action.reloadWindow"); + const settings: CppSettings = new CppSettings((vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length > 0) ? vscode.workspace.workspaceFolders[0]?.uri : undefined); + if (settings.intelliSenseEngine === "Disabled") { + languageServiceDisabled = true; + //getTemporaryCommandRegistrarInstance().disableLanguageServer(); + disposables.push(vscode.workspace.onDidChangeConfiguration(() => { + if (!reloadMessageShown && settings.intelliSenseEngine !== "Disabled") { + reloadMessageShown = true; + util.promptForReloadWindowDueToSettingsChange(); } - }); - } else if (!(await util.checkInstallJsonsExist())) { - // Check the Json files to declare if the extension has been installed successfully. - errMsg = localize("json.files.missing", "The C/C++ extension failed to install successfully. You will need to reinstall the extension for C/C++ language features to function properly."); - const downloadLink: string = localize("download.button", "Go to Download Page"); - vscode.window.showErrorMessage(errMsg, downloadLink).then(async (selection) => { - if (selection === downloadLink) { - vscode.env.openExternal(vscode.Uri.parse(releaseDownloadUrl)); + })); + } else { + disposables.push(vscode.workspace.onDidChangeConfiguration(() => { + if (!reloadMessageShown && settings.intelliSenseEngine === "Disabled") { + reloadMessageShown = true; + util.promptForReloadWindowDueToSettingsChange(); } - }); + })); } + // // Read archictures of binaries from install.lock + // const fileContents: string = await util.readFileText(util.getInstallLockPath()); + // // Assume current platform if install.lock is empty. + // let installedPlatformAndArchitecture: util.InstallLockContents = { + // platform: process.platform, + // architecture: arch + // }; + // if (fileContents.length !== 0) { + // try { + // installedPlatformAndArchitecture = JSON.parse(fileContents); + // } catch (error) { + // // If the contents of install.lock are corrupted, treat as if it's empty. + // } + // } + // + // // Check the main binaries files to declare if the extension has been installed successfully. + // if (process.platform !== installedPlatformAndArchitecture.platform + // || (arch !== installedPlatformAndArchitecture.architecture + // && !(process.platform === "win32" + // // On x64 Windows, allow x86 binaries. + // && ((arch === "x64" && installedPlatformAndArchitecture.architecture === "x86") + // // On arm64 Windows, allow x86 or x64 binaries. + // || (arch === "arm64" && ((installedPlatformAndArchitecture.architecture === "x86") || (installedPlatformAndArchitecture.architecture === "x64"))))) + // // On arm64 macOS, allow x64 binaries. + // && !(process.platform === "darwin" && arch === "arm64" && installedPlatformAndArchitecture.architecture === "x64"))) { + // // Check if the correct offline/insiders vsix is installed on the correct platform. + // const platformInfo: PlatformInformation = await PlatformInformation.GetPlatformInformation(); + // const vsixName: string = vsixNameForPlatform(platformInfo); + // const downloadLink: string = localize("download.button", "Go to Download Page"); + // errMsg = localize("native.binaries.not.supported", "This {0} {1} version of the extension is incompatible with your OS. Please download and install the \"{2}\" version of the extension.", GetOSName(installedPlatformAndArchitecture.platform), installedPlatformAndArchitecture.architecture, vsixName); + // vscode.window.showErrorMessage(errMsg, downloadLink).then(async (selection) => { + // if (selection === downloadLink) { + // vscode.env.openExternal(vscode.Uri.parse(releaseDownloadUrl)); + // } + // }); + // } else if (!(await util.checkInstallBinariesExist())) { + // errMsg = localize("extension.installation.failed", "The C/C++ extension failed to install successfully. You will need to repair or reinstall the extension for C/C++ language features to function properly."); + // const reload: string = localize("remove.extension", "Attempt to Repair"); + // vscode.window.showErrorMessage(errMsg, reload).then(async (value?: string) => { + // if (value === reload) { + // await util.removeInstallLockFile(); + // vscode.commands.executeCommand("workbench.action.reloadWindow"); + // } + // }); + // } else if (!(await util.checkInstallJsonsExist())) { + // // Check the Json files to declare if the extension has been installed successfully. + // errMsg = localize("json.files.missing", "The C/C++ extension failed to install successfully. You will need to reinstall the extension for C/C++ language features to function properly."); + // const downloadLink: string = localize("download.button", "Go to Download Page"); + // vscode.window.showErrorMessage(errMsg, downloadLink).then(async (selection) => { + // if (selection === downloadLink) { + // vscode.env.openExternal(vscode.Uri.parse(releaseDownloadUrl)); + // } + // }); + // } + return cppTools; } @@ -144,335 +176,353 @@ export function deactivate(): Thenable { return LanguageServer.deactivate(); } -async function processRuntimeDependencies(): Promise { - const installLockExists: boolean = await util.checkInstallLockFile(); - - setInstallationStage('getPlatformInfo'); - const info: PlatformInformation = await PlatformInformation.GetPlatformInformation(); - - let forceOnlineInstall: boolean = false; - if (info.platform === "darwin" && info.version) { - const darwinVersion: PersistentState = new PersistentState("Cpp.darwinVersion", info.version); - - // macOS version has changed - if (darwinVersion.Value !== info.version) { - const highSierraOrLowerRegex: RegExp = new RegExp('10\\.(1[0-3]|[0-9])(\\..*)*$'); - const lldbMiFolderPath: string = util.getExtensionFilePath('./debugAdapters/lldb-mi'); - - // For macOS and if a user has upgraded their OS, check to see if we are on Mojave or later - // and that the debugAdapters/lldb-mi folder exists. This will force a online install to get the correct binaries. - if (!highSierraOrLowerRegex.test(info.version) && - !await util.checkDirectoryExists(lldbMiFolderPath)) { - - forceOnlineInstall = true; - - setInstallationStage('cleanUpUnusedBinaries'); - await cleanUpUnusedBinaries(info); +// async function processRuntimeDependencies(): Promise { +// const installLockExists: boolean = await util.checkInstallLockFile(); + +// setInstallationStage('getPlatformInfo'); +// const info: PlatformInformation = await PlatformInformation.GetPlatformInformation(); + +// let forceOnlineInstall: boolean = false; +// if (info.platform === "darwin" && info.version) { +// const darwinVersion: PersistentState = new PersistentState("Cpp.darwinVersion", info.version); + +// // macOS version has changed +// if (darwinVersion.Value !== info.version) { +// const highSierraOrLowerRegex: RegExp = new RegExp('10\\.(1[0-3]|[0-9])(\\..*)*$'); +// const lldbMiFolderPath: string = util.getExtensionFilePath('./debugAdapters/lldb-mi'); + +// // For macOS and if a user has upgraded their OS, check to see if we are on Mojave or later +// // and that the debugAdapters/lldb-mi folder exists. This will force a online install to get the correct binaries. +// if (!highSierraOrLowerRegex.test(info.version) && +// !await util.checkDirectoryExists(lldbMiFolderPath)) { + +// forceOnlineInstall = true; + +// setInstallationStage('cleanUpUnusedBinaries'); +// await cleanUpUnusedBinaries(info); +// } +// } +// } + +// const doOfflineInstall: boolean = installLockExists && !forceOnlineInstall; + +// if (doOfflineInstall) { +// // Offline Scenario: Lock file exists but package.json has not had its activationEvents rewritten. +// if (util.packageJson.activationEvents && util.packageJson.activationEvents.length === 1) { +// try { +// await offlineInstallation(info); +// } catch (error) { +// getOutputChannelLogger().showErrorMessage(localize('initialization.failed', 'The installation of the C/C++ extension failed. Please see the output window for more information.')); +// showOutputChannel(); + +// // Send the failure telemetry since postInstall will not be called. +// sendTelemetry(info); +// } +// } else { +// // The extension has been installed and activated before. +// await finalizeExtensionActivation(); +// } +// } else { +// // No lock file, need to download and install dependencies. +// try { +// await onlineInstallation(info); +// } catch (errJS) { +// const error: Error = errJS as Error; +// handleError(error); + +// // Send the failure telemetry since postInstall will not be called. +// sendTelemetry(info); +// } +// } +// } + +// async function offlineInstallation(info: PlatformInformation): Promise { +// setInstallationType(InstallationType.Offline); + +// setInstallationStage('cleanUpUnusedBinaries'); +// await cleanUpUnusedBinaries(info); + +// setInstallationStage('makeOfflineBinariesExecutable'); +// await makeOfflineBinariesExecutable(info); + +// setInstallationStage('rewriteManifest'); +// await rewriteManifest(); + +// setInstallationStage('postInstall'); +// await postInstall(info); +// } + +// async function onlineInstallation(info: PlatformInformation): Promise { +// setInstallationType(InstallationType.Online); + +// await downloadAndInstallPackages(info); + +// setInstallationStage('rewriteManifest'); +// await rewriteManifest(); + +// setInstallationStage('touchInstallLockFile'); +// await touchInstallLockFile(info); + +// setInstallationStage('postInstall'); +// await postInstall(info); +// } + +// async function downloadAndInstallPackages(info: PlatformInformation): Promise { +// const outputChannelLogger: Logger = getOutputChannelLogger(); +// outputChannelLogger.appendLine(localize("updating.dependencies", "Updating C/C++ dependencies...")); + +// const packageManager: PackageManager = new PackageManager(info, outputChannelLogger); + +// return vscode.window.withProgress({ +// location: vscode.ProgressLocation.Notification, +// cancellable: false +// }, async (progress, token) => { + +// progress.report({ message: "C/C++ Extension" , increment: 0}); +// outputChannelLogger.appendLine(''); +// setInstallationStage('downloadPackages'); +// await packageManager.DownloadPackages(progress); + +// outputChannelLogger.appendLine(''); +// setInstallationStage('installPackages'); +// await packageManager.InstallPackages(progress); +// }); +// } + +// function packageMatchesPlatform(pkg: IPackage, info: PlatformInformation): boolean { +// return PlatformsMatch(pkg, info) && +// (pkg.architectures === undefined || ArchitecturesMatch(pkg, info)) && +// VersionsMatch(pkg, info); +// } + +// function invalidPackageVersion(pkg: IPackage, info: PlatformInformation): boolean { +// return PlatformsMatch(pkg, info) && +// (pkg.architectures === undefined || ArchitecturesMatch(pkg, info)) && +// !VersionsMatch(pkg, info); +// } + +async function makeBinariesExecutable(info: PlatformInformation): Promise { + + if (process.platform !== 'win32') { + const binaries: string[] = [ + "./bin/cpptools", + "./bin/cpptools-srv", + "./LLVM/bin/clang-format", + "./LLVM/bin/clang-tidy", + ]; + packages.forEach(p => { + if (p.binaries && p.binaries.length > 0 && + packageMatchesPlatform(p, info)) { + p.binaries.forEach(binary => promises.push(util.allowExecution(util.getExtensionFilePath(binary)))); } - } + }); } - const doOfflineInstall: boolean = installLockExists && !forceOnlineInstall; - - if (doOfflineInstall) { - // Offline Scenario: Lock file exists but package.json has not had its activationEvents rewritten. - if (util.packageJson.activationEvents && util.packageJson.activationEvents.length === 1) { - try { - await offlineInstallation(info); - } catch (error) { - getOutputChannelLogger().showErrorMessage(localize('initialization.failed', 'The installation of the C/C++ extension failed. Please see the output window for more information.')); - showOutputChannel(); - - // Send the failure telemetry since postInstall will not be called. - sendTelemetry(info); - } - } else { - // The extension has been installed and activated before. - await finalizeExtensionActivation(); - } - } else { - // No lock file, need to download and install dependencies. - try { - await onlineInstallation(info); - } catch (errJS) { - const error: Error = errJS as Error; - handleError(error); - - // Send the failure telemetry since postInstall will not be called. - sendTelemetry(info); - } - } + // const promises: Thenable[] = []; + // const packages: IPackage[] = util.packageJson["runtimeDependencies"]; + // packages.forEach(p => { + // if (p.binaries && p.binaries.length > 0 && + // packageMatchesPlatform(p, info)) { + // p.binaries.forEach(binary => promises.push(util.allowExecution(util.getExtensionFilePath(binary)))); + // } + // }); + // await Promise.all(promises); } -async function offlineInstallation(info: PlatformInformation): Promise { - setInstallationType(InstallationType.Offline); - - setInstallationStage('cleanUpUnusedBinaries'); - await cleanUpUnusedBinaries(info); - - setInstallationStage('makeOfflineBinariesExecutable'); - await makeOfflineBinariesExecutable(info); - - setInstallationStage('rewriteManifest'); - await rewriteManifest(); - - setInstallationStage('postInstall'); - await postInstall(info); -} - -async function onlineInstallation(info: PlatformInformation): Promise { - setInstallationType(InstallationType.Online); - - await downloadAndInstallPackages(info); - - setInstallationStage('rewriteManifest'); - await rewriteManifest(); - - setInstallationStage('touchInstallLockFile'); - await touchInstallLockFile(info); - - setInstallationStage('postInstall'); - await postInstall(info); -} - -async function downloadAndInstallPackages(info: PlatformInformation): Promise { - const outputChannelLogger: Logger = getOutputChannelLogger(); - outputChannelLogger.appendLine(localize("updating.dependencies", "Updating C/C++ dependencies...")); - - const packageManager: PackageManager = new PackageManager(info, outputChannelLogger); - - return vscode.window.withProgress({ - location: vscode.ProgressLocation.Notification, - cancellable: false - }, async (progress, token) => { - - progress.report({ message: "C/C++ Extension" , increment: 0}); - outputChannelLogger.appendLine(''); - setInstallationStage('downloadPackages'); - await packageManager.DownloadPackages(progress); - - outputChannelLogger.appendLine(''); - setInstallationStage('installPackages'); - await packageManager.InstallPackages(progress); - }); -} - -function packageMatchesPlatform(pkg: IPackage, info: PlatformInformation): boolean { - return PlatformsMatch(pkg, info) && - (pkg.architectures === undefined || ArchitecturesMatch(pkg, info)) && - VersionsMatch(pkg, info); -} - -function invalidPackageVersion(pkg: IPackage, info: PlatformInformation): boolean { - return PlatformsMatch(pkg, info) && - (pkg.architectures === undefined || ArchitecturesMatch(pkg, info)) && - !VersionsMatch(pkg, info); -} - -async function makeOfflineBinariesExecutable(info: PlatformInformation): Promise { - const promises: Thenable[] = []; - const packages: IPackage[] = util.packageJson["runtimeDependencies"]; - packages.forEach(p => { - if (p.binaries && p.binaries.length > 0 && - packageMatchesPlatform(p, info)) { - p.binaries.forEach(binary => promises.push(util.allowExecution(util.getExtensionFilePath(binary)))); - } - }); - await Promise.all(promises); -} - -async function cleanUpUnusedBinaries(info: PlatformInformation): Promise { - const promises: Thenable[] = []; - const packages: IPackage[] = util.packageJson["runtimeDependencies"]; - const logger: Logger = getOutputChannelLogger(); - - packages.forEach(p => { - if (p.binaries && p.binaries.length > 0 && - invalidPackageVersion(p, info)) { - p.binaries.forEach(binary => { - const path: string = util.getExtensionFilePath(binary); - if (fs.existsSync(path)) { - logger.appendLine(`deleting: ${path}`); - promises.push(util.deleteFile(path)); - } - }); - } - }); - await Promise.all(promises); -} - -function touchInstallLockFile(info: PlatformInformation): Promise { - return util.touchInstallLockFile(info); -} - -function handleError(error: Error): void { - const installationInformation: InstallationInformation = getInstallationInformation(); - installationInformation.hasError = true; - installationInformation.telemetryProperties['stage'] = installationInformation.stage ?? ""; - let errorMessage: string; - - if (error instanceof PackageManagerError) { - const packageError: PackageManagerError = error; - - installationInformation.telemetryProperties['error.methodName'] = packageError.methodName; - installationInformation.telemetryProperties['error.message'] = packageError.message; - - if (packageError.innerError) { - errorMessage = packageError.innerError.toString(); - installationInformation.telemetryProperties['error.innerError'] = util.removePotentialPII(errorMessage); - } else { - errorMessage = packageError.localizedMessageText; - } - - if (packageError.pkg) { - installationInformation.telemetryProperties['error.packageName'] = packageError.pkg.description; - installationInformation.telemetryProperties['error.packageUrl'] = packageError.pkg.url; - } - - if (packageError.errorCode) { - installationInformation.telemetryProperties['error.errorCode'] = util.removePotentialPII(packageError.errorCode); - } - } else { - errorMessage = error.toString(); - installationInformation.telemetryProperties['error.toString'] = util.removePotentialPII(errorMessage); - } - - const outputChannelLogger: Logger = getOutputChannelLogger(); - if (installationInformation.stage === 'downloadPackages') { - outputChannelLogger.appendLine(""); - } - // Show the actual message and not the sanitized one - outputChannelLogger.appendLine(localize('failed.at.stage', "Failed at stage: {0}", installationInformation.stage)); - outputChannelLogger.appendLine(errorMessage); - outputChannelLogger.appendLine(""); - outputChannelLogger.appendLine(localize('failed.at.stage2', 'If you work in an offline environment or repeatedly see this error, try downloading a version of the extension with all the dependencies pre-included from {0}, then use the "Install from VSIX" command in VS Code to install it.', releaseDownloadUrl)); - showOutputChannel(); -} +// async function cleanUpUnusedBinaries(info: PlatformInformation): Promise { +// const promises: Thenable[] = []; +// const packages: IPackage[] = util.packageJson["runtimeDependencies"]; +// const logger: Logger = getOutputChannelLogger(); + +// packages.forEach(p => { +// if (p.binaries && p.binaries.length > 0 && +// invalidPackageVersion(p, info)) { +// p.binaries.forEach(binary => { +// const path: string = util.getExtensionFilePath(binary); +// if (fs.existsSync(path)) { +// logger.appendLine(`deleting: ${path}`); +// promises.push(util.deleteFile(path)); +// } +// }); +// } +// }); +// await Promise.all(promises); +// } + +// function touchInstallLockFile(info: PlatformInformation): Promise { +// return util.touchInstallLockFile(info); +// } + +// function handleError(error: Error): void { +// const installationInformation: InstallationInformation = getInstallationInformation(); +// installationInformation.hasError = true; +// installationInformation.telemetryProperties['stage'] = installationInformation.stage ?? ""; +// let errorMessage: string; + +// if (error instanceof PackageManagerError) { +// const packageError: PackageManagerError = error; + +// installationInformation.telemetryProperties['error.methodName'] = packageError.methodName; +// installationInformation.telemetryProperties['error.message'] = packageError.message; + +// if (packageError.innerError) { +// errorMessage = packageError.innerError.toString(); +// installationInformation.telemetryProperties['error.innerError'] = util.removePotentialPII(errorMessage); +// } else { +// errorMessage = packageError.localizedMessageText; +// } + +// if (packageError.pkg) { +// installationInformation.telemetryProperties['error.packageName'] = packageError.pkg.description; +// installationInformation.telemetryProperties['error.packageUrl'] = packageError.pkg.url; +// } + +// if (packageError.errorCode) { +// installationInformation.telemetryProperties['error.errorCode'] = util.removePotentialPII(packageError.errorCode); +// } +// } else { +// errorMessage = error.toString(); +// installationInformation.telemetryProperties['error.toString'] = util.removePotentialPII(errorMessage); +// } + +// const outputChannelLogger: Logger = getOutputChannelLogger(); +// if (installationInformation.stage === 'downloadPackages') { +// outputChannelLogger.appendLine(""); +// } +// // Show the actual message and not the sanitized one +// outputChannelLogger.appendLine(localize('failed.at.stage', "Failed at stage: {0}", installationInformation.stage)); +// outputChannelLogger.appendLine(errorMessage); +// outputChannelLogger.appendLine(""); +// outputChannelLogger.appendLine(localize('failed.at.stage2', 'If you work in an offline environment or repeatedly see this error, try downloading a version of the extension with all the dependencies pre-included from {0}, then use the "Install from VSIX" command in VS Code to install it.', releaseDownloadUrl)); +// showOutputChannel(); +// } function sendTelemetry(info: PlatformInformation): boolean { - const installBlob: InstallationInformation = getInstallationInformation(); - const success: boolean = !installBlob.hasError; + let telemetryProperties: { [key: string]: string } = {}; + + //const installBlob: InstallationInformation = getInstallationInformation(); + const success: boolean = true;//!installBlob.hasError; - installBlob.telemetryProperties['success'] = success.toString(); - installBlob.telemetryProperties['type'] = installBlob.type === InstallationType.Online ? "online" : "offline"; + telemetryProperties['success'] = success.toString(); + //telemetryProperties['type'] = installBlob.type === InstallationType.Online ? "online" : "offline"; if (info.distribution) { - installBlob.telemetryProperties['linuxDistroName'] = info.distribution.name; - installBlob.telemetryProperties['linuxDistroVersion'] = info.distribution.version; + telemetryProperties['linuxDistroName'] = info.distribution.name; + telemetryProperties['linuxDistroVersion'] = info.distribution.version; } - if (success) { - util.setProgress(util.getProgressInstallSuccess()); - } + // if (success) { + // util.setProgress(util.getProgressInstallSuccess()); + // } - installBlob.telemetryProperties['osArchitecture'] = os.arch(); - installBlob.telemetryProperties['infoArchitecture'] = info.architecture; + telemetryProperties['osArchitecture'] = os.arch(); + telemetryProperties['infoArchitecture'] = info.architecture; - Telemetry.logDebuggerEvent("acquisition", installBlob.telemetryProperties); + Telemetry.logDebuggerEvent("acquisition", telemetryProperties); return success; } -async function postInstall(info: PlatformInformation): Promise { - const outputChannelLogger: Logger = getOutputChannelLogger(); - outputChannelLogger.appendLine(""); - outputChannelLogger.appendLine(localize('finished.installing.dependencies', "Finished installing dependencies")); - outputChannelLogger.appendLine(""); - - const installSuccess: boolean = sendTelemetry(info); - - // If there is a download failure, we shouldn't continue activating the extension in some broken state. - if (!installSuccess) { - throw new Error(localize("failed.installing.dependencies", "Failed installing dependencies")); - } else { - // Notify users if debugging may not be supported on their OS. - util.checkDistro(info); - - return finalizeExtensionActivation(); - } -} - -async function finalizeExtensionActivation(): Promise { - const settings: CppSettings = new CppSettings((vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length > 0) ? vscode.workspace.workspaceFolders[0]?.uri : undefined); - if (settings.intelliSenseEngine === "Disabled") { - languageServiceDisabled = true; - getTemporaryCommandRegistrarInstance().disableLanguageServer(); - disposables.push(vscode.workspace.onDidChangeConfiguration(() => { - if (!reloadMessageShown && settings.intelliSenseEngine !== "Disabled") { - reloadMessageShown = true; - util.promptForReloadWindowDueToSettingsChange(); - } - })); - return; - } - disposables.push(vscode.workspace.onDidChangeConfiguration(() => { - if (!reloadMessageShown && settings.intelliSenseEngine === "Disabled") { - reloadMessageShown = true; - util.promptForReloadWindowDueToSettingsChange(); - } - })); - getTemporaryCommandRegistrarInstance().activateLanguageServer(); -} - -function rewriteManifest(): Promise { - // Replace activationEvents with the events that the extension should be activated for subsequent sessions. - const packageJson: any = util.getRawPackageJson(); - - packageJson.activationEvents = [ - "onLanguage:c", - "onLanguage:cpp", - "onLanguage:cuda-cpp", - "onCommand:extension.pickNativeProcess", - "onCommand:extension.pickRemoteNativeProcess", - "onCommand:C_Cpp.BuildAndDebugActiveFile", - "onCommand:C_Cpp.RestartIntelliSenseForFile", - "onCommand:C_Cpp.ConfigurationEditJSON", - "onCommand:C_Cpp.ConfigurationEditUI", - "onCommand:C_Cpp.ConfigurationSelect", - "onCommand:C_Cpp.ConfigurationProviderSelect", - "onCommand:C_Cpp.SwitchHeaderSource", - "onCommand:C_Cpp.EnableErrorSquiggles", - "onCommand:C_Cpp.DisableErrorSquiggles", - "onCommand:C_Cpp.ToggleIncludeFallback", - "onCommand:C_Cpp.ToggleDimInactiveRegions", - "onCommand:C_Cpp.ResetDatabase", - "onCommand:C_Cpp.TakeSurvey", - "onCommand:C_Cpp.LogDiagnostics", - "onCommand:C_Cpp.RescanWorkspace", - "onCommand:C_Cpp.VcpkgClipboardInstallSuggested", - "onCommand:C_Cpp.VcpkgOnlineHelpSuggested", - "onCommand:C_Cpp.GenerateEditorConfig", - "onCommand:C_Cpp.GoToNextDirectiveInGroup", - "onCommand:C_Cpp.GoToPrevDirectiveInGroup", - "onCommand:C_Cpp.CheckForCompiler", - "onCommand:C_Cpp.RunCodeAnalysisOnActiveFile", - "onCommand:C_Cpp.RunCodeAnalysisOnOpenFiles", - "onCommand:C_Cpp.RunCodeAnalysisOnAllFiles", - "onCommand:C_Cpp.ClearCodeAnalysisSquiggles", - "onDebugInitialConfigurations", - "onDebugResolve:cppdbg", - "onDebugResolve:cppvsdbg", - "workspaceContains:/.vscode/c_cpp_properties.json", - "onFileSystem:cpptools-schema" - ]; - - let doTouchExtension: boolean = false; - - const packageJsonPath: string = util.getExtensionFilePath("package.json"); - if (packageJsonPath.includes(".vscode-insiders") || - packageJsonPath.includes(".vscode-server-insiders") || - packageJsonPath.includes(".vscode-exploration") || - packageJsonPath.includes(".vscode-server-exploration")) { - if (packageJson.contributes.configuration.properties['C_Cpp.updateChannel'].default === 'Default') { - packageJson.contributes.configuration.properties['C_Cpp.updateChannel'].default = 'Insiders'; - doTouchExtension = true; - } - } - - return util.writeFileText(util.getPackageJsonPath(), util.stringifyPackageJson(packageJson)).then(() => { - if (doTouchExtension) { - // This is required to prevent VS Code from using the cached version with the old updateChannel setting. - util.touchExtensionFolder(); - } - }); -} +// async function postInstall(info: PlatformInformation): Promise { +// const outputChannelLogger: Logger = getOutputChannelLogger(); +// outputChannelLogger.appendLine(""); +// outputChannelLogger.appendLine(localize('finished.installing.dependencies', "Finished installing dependencies")); +// outputChannelLogger.appendLine(""); + +// const installSuccess: boolean = sendTelemetry(info); + +// // If there is a download failure, we shouldn't continue activating the extension in some broken state. +// if (!installSuccess) { +// throw new Error(localize("failed.installing.dependencies", "Failed installing dependencies")); +// } else { +// // Notify users if debugging may not be supported on their OS. +// util.checkDistro(info); + +// return finalizeExtensionActivation(); +// } +// } + +// async function finalizeExtensionActivation(): Promise { +// const settings: CppSettings = new CppSettings((vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length > 0) ? vscode.workspace.workspaceFolders[0]?.uri : undefined); +// if (settings.intelliSenseEngine === "Disabled") { +// languageServiceDisabled = true; +// //getTemporaryCommandRegistrarInstance().disableLanguageServer(); +// disposables.push(vscode.workspace.onDidChangeConfiguration(() => { +// if (!reloadMessageShown && settings.intelliSenseEngine !== "Disabled") { +// reloadMessageShown = true; +// util.promptForReloadWindowDueToSettingsChange(); +// } +// })); +// return; +// } +// disposables.push(vscode.workspace.onDidChangeConfiguration(() => { +// if (!reloadMessageShown && settings.intelliSenseEngine === "Disabled") { +// reloadMessageShown = true; +// util.promptForReloadWindowDueToSettingsChange(); +// } +// })); +// //getTemporaryCommandRegistrarInstance().activateLanguageServer(); +// } + +// function rewriteManifest(): Promise { +// // Replace activationEvents with the events that the extension should be activated for subsequent sessions. +// const packageJson: any = util.getRawPackageJson(); + +// packageJson.activationEvents = [ +// "onLanguage:c", +// "onLanguage:cpp", +// "onLanguage:cuda-cpp", +// "onCommand:extension.pickNativeProcess", +// "onCommand:extension.pickRemoteNativeProcess", +// "onCommand:C_Cpp.BuildAndDebugActiveFile", +// "onCommand:C_Cpp.RestartIntelliSenseForFile", +// "onCommand:C_Cpp.ConfigurationEditJSON", +// "onCommand:C_Cpp.ConfigurationEditUI", +// "onCommand:C_Cpp.ConfigurationSelect", +// "onCommand:C_Cpp.ConfigurationProviderSelect", +// "onCommand:C_Cpp.SwitchHeaderSource", +// "onCommand:C_Cpp.EnableErrorSquiggles", +// "onCommand:C_Cpp.DisableErrorSquiggles", +// "onCommand:C_Cpp.ToggleIncludeFallback", +// "onCommand:C_Cpp.ToggleDimInactiveRegions", +// "onCommand:C_Cpp.ResetDatabase", +// "onCommand:C_Cpp.TakeSurvey", +// "onCommand:C_Cpp.LogDiagnostics", +// "onCommand:C_Cpp.RescanWorkspace", +// "onCommand:C_Cpp.VcpkgClipboardInstallSuggested", +// "onCommand:C_Cpp.VcpkgOnlineHelpSuggested", +// "onCommand:C_Cpp.GenerateEditorConfig", +// "onCommand:C_Cpp.GoToNextDirectiveInGroup", +// "onCommand:C_Cpp.GoToPrevDirectiveInGroup", +// "onCommand:C_Cpp.CheckForCompiler", +// "onCommand:C_Cpp.RunCodeAnalysisOnActiveFile", +// "onCommand:C_Cpp.RunCodeAnalysisOnOpenFiles", +// "onCommand:C_Cpp.RunCodeAnalysisOnAllFiles", +// "onCommand:C_Cpp.ClearCodeAnalysisSquiggles", +// "onDebugInitialConfigurations", +// "onDebugResolve:cppdbg", +// "onDebugResolve:cppvsdbg", +// "workspaceContains:/.vscode/c_cpp_properties.json", +// "onFileSystem:cpptools-schema" +// ]; + +// let doTouchExtension: boolean = false; + +// const packageJsonPath: string = util.getExtensionFilePath("package.json"); +// if (packageJsonPath.includes(".vscode-insiders") || +// packageJsonPath.includes(".vscode-server-insiders") || +// packageJsonPath.includes(".vscode-exploration") || +// packageJsonPath.includes(".vscode-server-exploration")) { +// if (packageJson.contributes.configuration.properties['C_Cpp.updateChannel'].default === 'Default') { +// packageJson.contributes.configuration.properties['C_Cpp.updateChannel'].default = 'Insiders'; +// doTouchExtension = true; +// } +// } + +// return util.writeFileText(util.getPackageJsonPath(), util.stringifyPackageJson(packageJson)).then(() => { +// if (doTouchExtension) { +// // This is required to prevent VS Code from using the cached version with the old updateChannel setting. +// util.touchExtensionFolder(); +// } +// }); +// } diff --git a/Extension/src/packageManager.ts b/Extension/src/packageManager.ts index 5daf135838..f646b20184 100644 --- a/Extension/src/packageManager.ts +++ b/Extension/src/packageManager.ts @@ -1,530 +1,530 @@ -/* -------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All Rights Reserved. - * See 'LICENSE' in the project root for license information. - * ------------------------------------------------------------------------------------------ */ - -import * as fs from 'fs'; -import * as net from 'net'; -import * as https from 'https'; -import * as path from 'path'; -import * as vscode from 'vscode'; -import * as url from 'url'; -import * as tmp from 'tmp'; -import * as yauzl from 'yauzl'; -import * as mkdirp from 'mkdirp'; - -import * as util from './common'; -import { PlatformInformation } from './platform'; -import * as Telemetry from './telemetry'; -import { IncomingMessage, ClientRequest } from 'http'; -import { Logger } from './logger'; -import * as nls from 'vscode-nls'; -import { Readable } from 'stream'; -import * as crypto from 'crypto'; - -nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })(); -const localize: nls.LocalizeFunc = nls.loadMessageBundle(); - -export function isValidPackage(buffer: Buffer, integrity: string): boolean { - if (integrity && integrity.length > 0) { - const hash: crypto.Hash = crypto.createHash('sha256'); - hash.update(buffer); - const value: string = hash.digest('hex').toUpperCase(); - return (value === integrity.toUpperCase()); - } - // No integrity has been specified - return false; -} - -export interface IPackage { - // Description of the package - description: string; - - // URL of the package - url: string; - - // Platforms for which the package should be downloaded - platforms: string[]; - - // Architectures for which the package is applicable - architectures: string[]; - - // OS Version regex to check if package is applicable - versionRegex: string; - - // A flag to indicate if 'versionRegex' should match or not match. - // Required if versionRegex is used. Default is false. - matchVersion: boolean; - - // Binaries in the package that should be executable when deployed - binaries: string[]; - - // Internal location to which the package was downloaded - tmpFile: tmp.FileResult; - - // sha256 hash of the package - integrity: string; -} - -export class PackageManagerError extends Error { - public localizedMessageText: string; - - constructor( - public message: string, - public localizedMessage: string, - public methodName: string, - public pkg: IPackage | null = null, - public innerError: Error | null = null, - public errorCode: string = '') { - super(message); - this.localizedMessageText = localizedMessage; - } -} - -export class PackageManagerWebResponseError extends PackageManagerError { - constructor( - public socket: net.Socket, - public message: string, - public localizedMessage: string, - public methodName: string, - public pkg: IPackage | null = null, - public innerError: Error | null = null, - public errorCode: string = '') { - super(message, localizedMessage, methodName, pkg, innerError, errorCode); - } -} - -export class PackageManager { - private allPackages?: IPackage[]; - - public constructor( - private platformInfo: PlatformInformation, - private outputChannel?: Logger) { - // Ensure our temp files get cleaned up in case of error - tmp.setGracefulCleanup(); - } - - public async DownloadPackages(progress: vscode.Progress<{ message?: string; increment?: number }>): Promise { - const packages: IPackage[] = await this.GetPackages(); - let count: number = 1; - return util.sequentialResolve(packages, async (pkg): Promise => { - progress.report({ message: localize("downloading.progress.description", "Downloading {0}", pkg.description), increment: this.GetIncrement(count, packages.length) }); - count += 1; - await this.DownloadPackage(pkg); - }); - } - - public async InstallPackages(progress: vscode.Progress<{ message?: string; increment?: number }>): Promise { - const packages: IPackage[] = await this.GetPackages(); - let count: number = 1; - return util.sequentialResolve(packages, async (pkg): Promise => { - progress.report({ message: localize("installing.progress.description", "Installing {0}", pkg.description), increment: this.GetIncrement(count, packages.length) }); - count += 1; - await this.InstallPackage(pkg); - }); - - } - - private GetIncrement(curStep: number, totalSteps: number): number { - // The first half of the progress bar is assigned to download progress, - // and the second half of the progress bar is assigned to install progress. - const maxIncrement: number = 100 / 2; - const increment: number = Math.floor(maxIncrement / totalSteps); - return (curStep !== totalSteps) ? increment : maxIncrement - (totalSteps - 1) * increment; - } - - public async GetPackages(): Promise { - const list: IPackage[] = await this.GetPackageList(); - return list.filter((value, index, array) => ArchitecturesMatch(value, this.platformInfo) && - PlatformsMatch(value, this.platformInfo) && - VersionsMatch(value, this.platformInfo) - ); - } - - private GetPackageList(): Promise { - return new Promise((resolve, reject) => { - if (!this.allPackages) { - if (util.packageJson.runtimeDependencies) { - this.allPackages = util.packageJson.runtimeDependencies; - - // Convert relative binary paths to absolute - for (const pkg of this.allPackages) { - if (pkg.binaries) { - pkg.binaries = pkg.binaries.map((value) => util.getExtensionFilePath(value)); - } - } - - resolve(this.allPackages); - } else { - reject(new PackageManagerError("Package manifest does not exist", localize("package.manager.missing", 'Package manifest does not exist'), 'GetPackageList')); - } - } else { - resolve(this.allPackages); - } - }); - } - - private async DownloadPackage(pkg: IPackage): Promise { - this.AppendChannel(localize("downloading.package", "Downloading package '{0}' ", pkg.description)); - - const tmpResult: tmp.FileResult = await this.CreateTempFile(pkg); - await this.DownloadPackageWithRetries(pkg, tmpResult); - } - - private async CreateTempFile(pkg: IPackage): Promise { - return new Promise((resolve, reject) => { - tmp.file({ prefix: "package-" }, (err, path, fd, cleanupCallback) => { - if (err) { - return reject(new PackageManagerError("Error from temp.file", localize("error.from", 'Error from {0}', "temp.file"), 'DownloadPackage', pkg, err)); - } - - return resolve({ name: path, fd: fd, removeCallback: cleanupCallback }); - }); - }); - } - - private async DownloadPackageWithRetries(pkg: IPackage, tmpResult: tmp.FileResult): Promise { - pkg.tmpFile = tmpResult; - - let success: boolean = false; - let lastError: Error | null = null; - let retryCount: number = 0; - const MAX_RETRIES: number = 10; - - // Retry the download at most MAX_RETRIES times with 2-32 seconds delay. - do { - try { - await this.DownloadFile(pkg.url, pkg, retryCount); - success = true; - } catch (errJS) { - const error: Error = errJS as Error; - retryCount += 1; - lastError = error; - if (retryCount >= MAX_RETRIES) { - this.AppendChannel(" " + localize("failed.download.url", "Failed to download {0}", pkg.url)); - throw error; - } else { - this.AppendChannel(" " + localize("failed.retrying", "Failed. Retrying...")); - continue; - } - } - } while (!success && retryCount < MAX_RETRIES); - - this.AppendLineChannel(" " + localize("done", "Done!")); - if (retryCount !== 0) { - // Log telemetry to see if retrying helps. - const telemetryProperties: { [key: string]: string } = {}; - telemetryProperties["success"] = success ? `OnRetry${retryCount}` : 'false'; - if (lastError instanceof PackageManagerError) { - const packageError: PackageManagerError = lastError; - telemetryProperties['error.methodName'] = packageError.methodName; - telemetryProperties['error.message'] = packageError.message; - if (packageError.pkg) { - telemetryProperties['error.packageName'] = packageError.pkg.description; - telemetryProperties['error.packageUrl'] = packageError.pkg.url; - } - if (packageError.errorCode) { - telemetryProperties['error.errorCode'] = packageError.errorCode; - } - } - Telemetry.logDebuggerEvent("acquisition", telemetryProperties); - } - } - - // reloadCpptoolsJson in main.ts uses ~25% of this function. - private DownloadFile(urlString: any, pkg: IPackage, delay: number): Promise { - const parsedUrl: url.Url = url.parse(urlString); - const proxyStrictSSL: any = vscode.workspace.getConfiguration().get("http.proxyStrictSSL", true); - - const options: https.RequestOptions = { - host: parsedUrl.host, - path: parsedUrl.path, - agent: util.getHttpsProxyAgent(), - rejectUnauthorized: proxyStrictSSL - }; - - const buffers: Buffer[] = []; - return new Promise((resolve, reject) => { - let secondsDelay: number = Math.min(Math.pow(2, delay), 15); - if (secondsDelay === 1) { - secondsDelay = 0; - } - if (secondsDelay > 4) { - this.AppendChannel(localize("waiting.seconds", "Waiting {0} seconds...", secondsDelay)); - } - setTimeout(() => { - if (!pkg.tmpFile || pkg.tmpFile.fd === 0) { - return reject(new PackageManagerError('Temporary Package file unavailable', localize("temp.package.unavailable", 'Temporary Package file unavailable'), 'DownloadFile', pkg)); - } - - const handleHttpResponse: (response: IncomingMessage) => void = (response: IncomingMessage) => { - if (response.statusCode === 301 || response.statusCode === 302) { - // Redirect - download from new location - let redirectUrl: string | string[]; - if (typeof response.headers.location === "string") { - redirectUrl = response.headers.location; - } else { - if (!response.headers.location) { - return reject(new PackageManagerError('Invalid download location received', localize("invalid.download.location.received", 'Invalid download location received'), 'DownloadFile', pkg)); - } - redirectUrl = response.headers.location[0]; - } - return resolve(this.DownloadFile(redirectUrl, pkg, 0)); - } else if (response.statusCode !== 200) { - if (response.statusCode === undefined || response.statusCode === null) { - return reject(new PackageManagerError('Invalid response code received', localize("invalid.response.code.received", 'Invalid response code received'), 'DownloadFile', pkg)); - } - // Download failed - print error message - const error: Error = new Error(localize("failed.web.error", "failed (error code '{0}')", response.statusCode)); - return reject(new PackageManagerWebResponseError(response.socket, 'HTTP/HTTPS Response Error', localize("web.response.error", 'HTTP/HTTPS Response Error'), 'DownloadFile', pkg, error, response.statusCode.toString())); - } else { - // Downloading - hook up events - let contentLength: any = response.headers['content-length']; - if (typeof response.headers['content-length'] === "string") { - contentLength = response.headers['content-length']; - } else { - if (response.headers['content-length'] === undefined || response.headers['content-length'] === null) { - return reject(new PackageManagerError('Invalid content length location received', localize("invalid.content.length.received", 'Invalid content length location received'), 'DownloadFile', pkg)); - } - contentLength = response.headers['content-length'][0]; - } - const packageSize: number = parseInt(contentLength, 10); - const downloadPercentage: number = 0; - let dots: number = 0; - const tmpFile: fs.WriteStream = fs.createWriteStream("", { fd: pkg.tmpFile.fd }); - - this.AppendChannel(`(${Math.ceil(packageSize / 1024)} KB) `); - - response.on('data', (data) => { - buffers.push(data); - // Update dots after package name in output console - const newDots: number = Math.ceil(downloadPercentage / 5); - if (newDots > dots) { - this.AppendChannel(".".repeat(newDots - dots)); - dots = newDots; - } - }); - - response.on('end', () => { - const packageBuffer: Buffer = Buffer.concat(buffers); - if (isValidPackage(packageBuffer, pkg.integrity)) { - resolve(); - } else { - reject(new PackageManagerError('Invalid content received. Hash is incorrect.', localize("invalid.content.received", 'Invalid content received. Hash is incorrect.'), 'DownloadFile', pkg)); - } - }); - - response.on('error', (errJS) => { - const error: Error = errJS as Error; - reject(new PackageManagerWebResponseError(response.socket, 'HTTP/HTTPS Response Error', localize("web.response.error", 'HTTP/HTTPS Response Error'), 'DownloadFile', pkg, error, error.name)); - }); - - // Begin piping data from the response to the package file - response.pipe(tmpFile, { end: false }); - } - }; - - const request: ClientRequest = https.request(options, handleHttpResponse); - - request.on('error', (error) => - reject(new PackageManagerError( - 'HTTP/HTTPS Request error' + (urlString.includes("fwlink") ? ": fwlink" : ""), - localize("web.request.error", 'HTTP/HTTPS Request error') + (urlString.includes("fwlink") ? ": fwlink" : ""), - 'DownloadFile', pkg, error, error.message))); - - // Execute the request - request.end(); - }, secondsDelay * 1000); - }); - } - - private InstallPackage(pkg: IPackage): Promise { - this.AppendLineChannel(localize("installing.package", "Installing package '{0}'", pkg.description)); - - return new Promise((resolve, reject) => { - if (!pkg.tmpFile || pkg.tmpFile.fd === 0) { - return reject(new PackageManagerError('Downloaded file unavailable', localize("downloaded.unavailable", 'Downloaded file unavailable'), 'InstallPackage', pkg)); - } - - yauzl.fromFd(pkg.tmpFile.fd, { lazyEntries: true, autoClose: true }, (err, zipfile) => { - if (err || !zipfile) { - return reject(new PackageManagerError('Zip file error', localize("zip.file.error", 'Zip file error'), 'InstallPackage', pkg, err)); - } - - // setup zip file events - - // Keep track of any error that occurs, but don't resolve or reject the promise until the file is closed. - let pendingError: Error | undefined; - zipfile.on('close', () => { - if (!pendingError) { - resolve(); - } else { - reject(pendingError); - } - }); - - zipfile.on('error', err => { - // Don't call reject() a second time. - // Errors can also arise from readStream and writeStream. - if (!pendingError) { - pendingError = new PackageManagerError('Zip file error', localize("zip.file.error", 'Zip file error'), 'InstallPackage', pkg, err, err.code); - zipfile.close(); - } - }); - - zipfile.on('entry', (entry: yauzl.Entry) => { - const absoluteEntryPath: string = util.getExtensionFilePath(entry.fileName); - - if (entry.fileName.endsWith("/")) { - // Directory - create it - mkdirp(absoluteEntryPath, { mode: 0o775 }, (err) => { - if (err) { - pendingError = new PackageManagerError('Error creating directory', localize("create.directory.error", 'Error creating directory'), 'InstallPackage', pkg, err, err.code); - zipfile.close(); - return; - } - - zipfile.readEntry(); - }); - } else { - util.checkFileExists(absoluteEntryPath).then((exists: boolean) => { - if (!exists) { - // File - extract it - zipfile.openReadStream(entry, (err, readStream: Readable | undefined) => { - if (err || !readStream) { - pendingError = new PackageManagerError('Error reading zip stream', localize("zip.stream.error", 'Error reading zip stream'), 'InstallPackage', pkg, err); - zipfile.close(); - return; - } - - mkdirp(path.dirname(absoluteEntryPath), { mode: 0o775 }, async (err) => { - if (err) { - pendingError = new PackageManagerError('Error creating directory', localize("create.directory.error", 'Error creating directory'), 'InstallPackage', pkg, err, err.code); - zipfile.close(); - return; - } - - // Create as a .tmp file to avoid partially unzipped files - // counting as completed files. - const absoluteEntryTempFile: string = absoluteEntryPath + ".tmp"; - if (await util.checkFileExists(absoluteEntryTempFile)) { - try { - await util.unlinkAsync(absoluteEntryTempFile); - } catch (errJS) { - const err: Error = errJS as Error; - pendingError = new PackageManagerError(`Error unlinking file ${absoluteEntryTempFile}`, localize("unlink.error", "Error unlinking file {0}", absoluteEntryTempFile), 'InstallPackage', pkg, err); - zipfile.close(); - return; - } - } - - // Make sure executable files have correct permissions when extracted - const fileMode: number = (this.platformInfo.platform !== "win32" && pkg.binaries && pkg.binaries.indexOf(absoluteEntryPath) !== -1) ? 0o755 : 0o664; - const writeStream: fs.WriteStream = fs.createWriteStream(absoluteEntryTempFile, { mode: fileMode }); - - writeStream.on('close', async () => { - // Remove .tmp extension from the file, if there was no error. - // Otherwise, delete it. - // Don't move on to the next entry, if we've already called reject(), in - // which case zipfile.close() will already have been called. - if (!pendingError) { - try { - await util.renameAsync(absoluteEntryTempFile, absoluteEntryPath); - } catch (errJS) { - const err: Error = errJS as Error; - pendingError = new PackageManagerError(`Error renaming file ${absoluteEntryTempFile}`, localize("rename.error", "Error renaming file {0}", absoluteEntryTempFile), 'InstallPackage', pkg, err); - zipfile.close(); - return; - } - // Wait until output is done writing before reading the next zip entry. - // Otherwise, it's possible to try to launch the .exe before it is done being created. - zipfile.readEntry(); - } else { - try { - await util.unlinkAsync(absoluteEntryTempFile); - } catch (err) { - // Ignore failure to delete temp file. We already have an error to return. - } - } - }); - - readStream.on('error', (err) => { - // Don't call reject() a second time. - if (!pendingError) { - pendingError = new PackageManagerError('Error in readStream', localize("read.stream.error", 'Error in read stream'), 'InstallPackage', pkg, err); - zipfile.close(); - } - }); - - writeStream.on('error', (err) => { - // Don't call reject() a second time. - if (!pendingError) { - pendingError = new PackageManagerError('Error in writeStream', localize("write.stream.error", 'Error in write stream'), 'InstallPackage', pkg, err); - zipfile.close(); - } - }); - - readStream.pipe(writeStream); - }); - }); - } else { - // Skip the message for text files, because there is a duplicate text file unzipped. - if (path.extname(absoluteEntryPath) !== ".txt") { - this.AppendLineChannel(localize("file.already.exists", "Warning: File '{0}' already exists and was not updated.", absoluteEntryPath)); - } - zipfile.readEntry(); - } - }); - } - }); - - zipfile.readEntry(); - }); - }).then(() => { - // Clean up temp file - pkg.tmpFile.removeCallback(); - }); - } - - private AppendChannel(text: string): void { - if (this.outputChannel) { - this.outputChannel.append(text); - } - } - - private AppendLineChannel(text: string): void { - if (this.outputChannel) { - this.outputChannel.appendLine(text); - } - } -} - -export function VersionsMatch(pkg: IPackage, info: PlatformInformation): boolean { - if (pkg.versionRegex) { - // If we have a versionRegex but did not get a platformVersion - if (!info.version) { - // If we are expecting to match the versionRegex, return false since there was no version found. - // - // If we are expecting to not match the versionRegex, return true since we are expecting to - // not match the version string, the only match would be if versionRegex was not set. - return !pkg.matchVersion; - } - const regex: RegExp = new RegExp(pkg.versionRegex); - - return (pkg.matchVersion ? - regex.test(info.version) : - !regex.test(info.version) - ); - } - - // No versionRegex provided. - return true; -} - -export function ArchitecturesMatch(value: IPackage, info: PlatformInformation): boolean { - return !value.architectures || (value.architectures.indexOf(info.architecture) !== -1); -} - -export function PlatformsMatch(value: IPackage, info: PlatformInformation): boolean { - return !value.platforms || value.platforms.indexOf(info.platform) !== -1; -} +// /* -------------------------------------------------------------------------------------------- +// * Copyright (c) Microsoft Corporation. All Rights Reserved. +// * See 'LICENSE' in the project root for license information. +// * ------------------------------------------------------------------------------------------ */ + +// import * as fs from 'fs'; +// import * as net from 'net'; +// import * as https from 'https'; +// import * as path from 'path'; +// import * as vscode from 'vscode'; +// import * as url from 'url'; +// import * as tmp from 'tmp'; +// import * as yauzl from 'yauzl'; +// import * as mkdirp from 'mkdirp'; + +// import * as util from './common'; +// import { PlatformInformation } from './platform'; +// import * as Telemetry from './telemetry'; +// import { IncomingMessage, ClientRequest } from 'http'; +// import { Logger } from './logger'; +// import * as nls from 'vscode-nls'; +// import { Readable } from 'stream'; +// import * as crypto from 'crypto'; + +// nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })(); +// const localize: nls.LocalizeFunc = nls.loadMessageBundle(); + +// export function isValidPackage(buffer: Buffer, integrity: string): boolean { +// if (integrity && integrity.length > 0) { +// const hash: crypto.Hash = crypto.createHash('sha256'); +// hash.update(buffer); +// const value: string = hash.digest('hex').toUpperCase(); +// return (value === integrity.toUpperCase()); +// } +// // No integrity has been specified +// return false; +// } + +// export interface IPackage { +// // Description of the package +// description: string; + +// // URL of the package +// url: string; + +// // Platforms for which the package should be downloaded +// platforms: string[]; + +// // Architectures for which the package is applicable +// architectures: string[]; + +// // OS Version regex to check if package is applicable +// versionRegex: string; + +// // A flag to indicate if 'versionRegex' should match or not match. +// // Required if versionRegex is used. Default is false. +// matchVersion: boolean; + +// // Binaries in the package that should be executable when deployed +// binaries: string[]; + +// // Internal location to which the package was downloaded +// tmpFile: tmp.FileResult; + +// // sha256 hash of the package +// integrity: string; +// } + +// export class PackageManagerError extends Error { +// public localizedMessageText: string; + +// constructor( +// public message: string, +// public localizedMessage: string, +// public methodName: string, +// public pkg: IPackage | null = null, +// public innerError: Error | null = null, +// public errorCode: string = '') { +// super(message); +// this.localizedMessageText = localizedMessage; +// } +// } + +// export class PackageManagerWebResponseError extends PackageManagerError { +// constructor( +// public socket: net.Socket, +// public message: string, +// public localizedMessage: string, +// public methodName: string, +// public pkg: IPackage | null = null, +// public innerError: Error | null = null, +// public errorCode: string = '') { +// super(message, localizedMessage, methodName, pkg, innerError, errorCode); +// } +// } + +// export class PackageManager { +// private allPackages?: IPackage[]; + +// public constructor( +// private platformInfo: PlatformInformation, +// private outputChannel?: Logger) { +// // Ensure our temp files get cleaned up in case of error +// tmp.setGracefulCleanup(); +// } + +// public async DownloadPackages(progress: vscode.Progress<{ message?: string; increment?: number }>): Promise { +// const packages: IPackage[] = await this.GetPackages(); +// let count: number = 1; +// return util.sequentialResolve(packages, async (pkg): Promise => { +// progress.report({ message: localize("downloading.progress.description", "Downloading {0}", pkg.description), increment: this.GetIncrement(count, packages.length) }); +// count += 1; +// await this.DownloadPackage(pkg); +// }); +// } + +// public async InstallPackages(progress: vscode.Progress<{ message?: string; increment?: number }>): Promise { +// const packages: IPackage[] = await this.GetPackages(); +// let count: number = 1; +// return util.sequentialResolve(packages, async (pkg): Promise => { +// progress.report({ message: localize("installing.progress.description", "Installing {0}", pkg.description), increment: this.GetIncrement(count, packages.length) }); +// count += 1; +// await this.InstallPackage(pkg); +// }); + +// } + +// private GetIncrement(curStep: number, totalSteps: number): number { +// // The first half of the progress bar is assigned to download progress, +// // and the second half of the progress bar is assigned to install progress. +// const maxIncrement: number = 100 / 2; +// const increment: number = Math.floor(maxIncrement / totalSteps); +// return (curStep !== totalSteps) ? increment : maxIncrement - (totalSteps - 1) * increment; +// } + +// public async GetPackages(): Promise { +// const list: IPackage[] = await this.GetPackageList(); +// return list.filter((value, index, array) => ArchitecturesMatch(value, this.platformInfo) && +// PlatformsMatch(value, this.platformInfo) && +// VersionsMatch(value, this.platformInfo) +// ); +// } + +// private GetPackageList(): Promise { +// return new Promise((resolve, reject) => { +// if (!this.allPackages) { +// if (util.packageJson.runtimeDependencies) { +// this.allPackages = util.packageJson.runtimeDependencies; + +// // Convert relative binary paths to absolute +// for (const pkg of this.allPackages) { +// if (pkg.binaries) { +// pkg.binaries = pkg.binaries.map((value) => util.getExtensionFilePath(value)); +// } +// } + +// resolve(this.allPackages); +// } else { +// reject(new PackageManagerError("Package manifest does not exist", localize("package.manager.missing", 'Package manifest does not exist'), 'GetPackageList')); +// } +// } else { +// resolve(this.allPackages); +// } +// }); +// } + +// private async DownloadPackage(pkg: IPackage): Promise { +// this.AppendChannel(localize("downloading.package", "Downloading package '{0}' ", pkg.description)); + +// const tmpResult: tmp.FileResult = await this.CreateTempFile(pkg); +// await this.DownloadPackageWithRetries(pkg, tmpResult); +// } + +// private async CreateTempFile(pkg: IPackage): Promise { +// return new Promise((resolve, reject) => { +// tmp.file({ prefix: "package-" }, (err, path, fd, cleanupCallback) => { +// if (err) { +// return reject(new PackageManagerError("Error from temp.file", localize("error.from", 'Error from {0}', "temp.file"), 'DownloadPackage', pkg, err)); +// } + +// return resolve({ name: path, fd: fd, removeCallback: cleanupCallback }); +// }); +// }); +// } + +// private async DownloadPackageWithRetries(pkg: IPackage, tmpResult: tmp.FileResult): Promise { +// pkg.tmpFile = tmpResult; + +// let success: boolean = false; +// let lastError: Error | null = null; +// let retryCount: number = 0; +// const MAX_RETRIES: number = 10; + +// // Retry the download at most MAX_RETRIES times with 2-32 seconds delay. +// do { +// try { +// await this.DownloadFile(pkg.url, pkg, retryCount); +// success = true; +// } catch (errJS) { +// const error: Error = errJS as Error; +// retryCount += 1; +// lastError = error; +// if (retryCount >= MAX_RETRIES) { +// this.AppendChannel(" " + localize("failed.download.url", "Failed to download {0}", pkg.url)); +// throw error; +// } else { +// this.AppendChannel(" " + localize("failed.retrying", "Failed. Retrying...")); +// continue; +// } +// } +// } while (!success && retryCount < MAX_RETRIES); + +// this.AppendLineChannel(" " + localize("done", "Done!")); +// if (retryCount !== 0) { +// // Log telemetry to see if retrying helps. +// const telemetryProperties: { [key: string]: string } = {}; +// telemetryProperties["success"] = success ? `OnRetry${retryCount}` : 'false'; +// if (lastError instanceof PackageManagerError) { +// const packageError: PackageManagerError = lastError; +// telemetryProperties['error.methodName'] = packageError.methodName; +// telemetryProperties['error.message'] = packageError.message; +// if (packageError.pkg) { +// telemetryProperties['error.packageName'] = packageError.pkg.description; +// telemetryProperties['error.packageUrl'] = packageError.pkg.url; +// } +// if (packageError.errorCode) { +// telemetryProperties['error.errorCode'] = packageError.errorCode; +// } +// } +// Telemetry.logDebuggerEvent("acquisition", telemetryProperties); +// } +// } + +// // reloadCpptoolsJson in main.ts uses ~25% of this function. +// private DownloadFile(urlString: any, pkg: IPackage, delay: number): Promise { +// const parsedUrl: url.Url = url.parse(urlString); +// const proxyStrictSSL: any = vscode.workspace.getConfiguration().get("http.proxyStrictSSL", true); + +// const options: https.RequestOptions = { +// host: parsedUrl.host, +// path: parsedUrl.path, +// agent: util.getHttpsProxyAgent(), +// rejectUnauthorized: proxyStrictSSL +// }; + +// const buffers: Buffer[] = []; +// return new Promise((resolve, reject) => { +// let secondsDelay: number = Math.min(Math.pow(2, delay), 15); +// if (secondsDelay === 1) { +// secondsDelay = 0; +// } +// if (secondsDelay > 4) { +// this.AppendChannel(localize("waiting.seconds", "Waiting {0} seconds...", secondsDelay)); +// } +// setTimeout(() => { +// if (!pkg.tmpFile || pkg.tmpFile.fd === 0) { +// return reject(new PackageManagerError('Temporary Package file unavailable', localize("temp.package.unavailable", 'Temporary Package file unavailable'), 'DownloadFile', pkg)); +// } + +// const handleHttpResponse: (response: IncomingMessage) => void = (response: IncomingMessage) => { +// if (response.statusCode === 301 || response.statusCode === 302) { +// // Redirect - download from new location +// let redirectUrl: string | string[]; +// if (typeof response.headers.location === "string") { +// redirectUrl = response.headers.location; +// } else { +// if (!response.headers.location) { +// return reject(new PackageManagerError('Invalid download location received', localize("invalid.download.location.received", 'Invalid download location received'), 'DownloadFile', pkg)); +// } +// redirectUrl = response.headers.location[0]; +// } +// return resolve(this.DownloadFile(redirectUrl, pkg, 0)); +// } else if (response.statusCode !== 200) { +// if (response.statusCode === undefined || response.statusCode === null) { +// return reject(new PackageManagerError('Invalid response code received', localize("invalid.response.code.received", 'Invalid response code received'), 'DownloadFile', pkg)); +// } +// // Download failed - print error message +// const error: Error = new Error(localize("failed.web.error", "failed (error code '{0}')", response.statusCode)); +// return reject(new PackageManagerWebResponseError(response.socket, 'HTTP/HTTPS Response Error', localize("web.response.error", 'HTTP/HTTPS Response Error'), 'DownloadFile', pkg, error, response.statusCode.toString())); +// } else { +// // Downloading - hook up events +// let contentLength: any = response.headers['content-length']; +// if (typeof response.headers['content-length'] === "string") { +// contentLength = response.headers['content-length']; +// } else { +// if (response.headers['content-length'] === undefined || response.headers['content-length'] === null) { +// return reject(new PackageManagerError('Invalid content length location received', localize("invalid.content.length.received", 'Invalid content length location received'), 'DownloadFile', pkg)); +// } +// contentLength = response.headers['content-length'][0]; +// } +// const packageSize: number = parseInt(contentLength, 10); +// const downloadPercentage: number = 0; +// let dots: number = 0; +// const tmpFile: fs.WriteStream = fs.createWriteStream("", { fd: pkg.tmpFile.fd }); + +// this.AppendChannel(`(${Math.ceil(packageSize / 1024)} KB) `); + +// response.on('data', (data) => { +// buffers.push(data); +// // Update dots after package name in output console +// const newDots: number = Math.ceil(downloadPercentage / 5); +// if (newDots > dots) { +// this.AppendChannel(".".repeat(newDots - dots)); +// dots = newDots; +// } +// }); + +// response.on('end', () => { +// const packageBuffer: Buffer = Buffer.concat(buffers); +// if (isValidPackage(packageBuffer, pkg.integrity)) { +// resolve(); +// } else { +// reject(new PackageManagerError('Invalid content received. Hash is incorrect.', localize("invalid.content.received", 'Invalid content received. Hash is incorrect.'), 'DownloadFile', pkg)); +// } +// }); + +// response.on('error', (errJS) => { +// const error: Error = errJS as Error; +// reject(new PackageManagerWebResponseError(response.socket, 'HTTP/HTTPS Response Error', localize("web.response.error", 'HTTP/HTTPS Response Error'), 'DownloadFile', pkg, error, error.name)); +// }); + +// // Begin piping data from the response to the package file +// response.pipe(tmpFile, { end: false }); +// } +// }; + +// const request: ClientRequest = https.request(options, handleHttpResponse); + +// request.on('error', (error) => +// reject(new PackageManagerError( +// 'HTTP/HTTPS Request error' + (urlString.includes("fwlink") ? ": fwlink" : ""), +// localize("web.request.error", 'HTTP/HTTPS Request error') + (urlString.includes("fwlink") ? ": fwlink" : ""), +// 'DownloadFile', pkg, error, error.message))); + +// // Execute the request +// request.end(); +// }, secondsDelay * 1000); +// }); +// } + +// private InstallPackage(pkg: IPackage): Promise { +// this.AppendLineChannel(localize("installing.package", "Installing package '{0}'", pkg.description)); + +// return new Promise((resolve, reject) => { +// if (!pkg.tmpFile || pkg.tmpFile.fd === 0) { +// return reject(new PackageManagerError('Downloaded file unavailable', localize("downloaded.unavailable", 'Downloaded file unavailable'), 'InstallPackage', pkg)); +// } + +// yauzl.fromFd(pkg.tmpFile.fd, { lazyEntries: true, autoClose: true }, (err, zipfile) => { +// if (err || !zipfile) { +// return reject(new PackageManagerError('Zip file error', localize("zip.file.error", 'Zip file error'), 'InstallPackage', pkg, err)); +// } + +// // setup zip file events + +// // Keep track of any error that occurs, but don't resolve or reject the promise until the file is closed. +// let pendingError: Error | undefined; +// zipfile.on('close', () => { +// if (!pendingError) { +// resolve(); +// } else { +// reject(pendingError); +// } +// }); + +// zipfile.on('error', err => { +// // Don't call reject() a second time. +// // Errors can also arise from readStream and writeStream. +// if (!pendingError) { +// pendingError = new PackageManagerError('Zip file error', localize("zip.file.error", 'Zip file error'), 'InstallPackage', pkg, err, err.code); +// zipfile.close(); +// } +// }); + +// zipfile.on('entry', (entry: yauzl.Entry) => { +// const absoluteEntryPath: string = util.getExtensionFilePath(entry.fileName); + +// if (entry.fileName.endsWith("/")) { +// // Directory - create it +// mkdirp(absoluteEntryPath, { mode: 0o775 }, (err) => { +// if (err) { +// pendingError = new PackageManagerError('Error creating directory', localize("create.directory.error", 'Error creating directory'), 'InstallPackage', pkg, err, err.code); +// zipfile.close(); +// return; +// } + +// zipfile.readEntry(); +// }); +// } else { +// util.checkFileExists(absoluteEntryPath).then((exists: boolean) => { +// if (!exists) { +// // File - extract it +// zipfile.openReadStream(entry, (err, readStream: Readable | undefined) => { +// if (err || !readStream) { +// pendingError = new PackageManagerError('Error reading zip stream', localize("zip.stream.error", 'Error reading zip stream'), 'InstallPackage', pkg, err); +// zipfile.close(); +// return; +// } + +// mkdirp(path.dirname(absoluteEntryPath), { mode: 0o775 }, async (err) => { +// if (err) { +// pendingError = new PackageManagerError('Error creating directory', localize("create.directory.error", 'Error creating directory'), 'InstallPackage', pkg, err, err.code); +// zipfile.close(); +// return; +// } + +// // Create as a .tmp file to avoid partially unzipped files +// // counting as completed files. +// const absoluteEntryTempFile: string = absoluteEntryPath + ".tmp"; +// if (await util.checkFileExists(absoluteEntryTempFile)) { +// try { +// await util.unlinkAsync(absoluteEntryTempFile); +// } catch (errJS) { +// const err: Error = errJS as Error; +// pendingError = new PackageManagerError(`Error unlinking file ${absoluteEntryTempFile}`, localize("unlink.error", "Error unlinking file {0}", absoluteEntryTempFile), 'InstallPackage', pkg, err); +// zipfile.close(); +// return; +// } +// } + +// // Make sure executable files have correct permissions when extracted +// const fileMode: number = (this.platformInfo.platform !== "win32" && pkg.binaries && pkg.binaries.indexOf(absoluteEntryPath) !== -1) ? 0o755 : 0o664; +// const writeStream: fs.WriteStream = fs.createWriteStream(absoluteEntryTempFile, { mode: fileMode }); + +// writeStream.on('close', async () => { +// // Remove .tmp extension from the file, if there was no error. +// // Otherwise, delete it. +// // Don't move on to the next entry, if we've already called reject(), in +// // which case zipfile.close() will already have been called. +// if (!pendingError) { +// try { +// await util.renameAsync(absoluteEntryTempFile, absoluteEntryPath); +// } catch (errJS) { +// const err: Error = errJS as Error; +// pendingError = new PackageManagerError(`Error renaming file ${absoluteEntryTempFile}`, localize("rename.error", "Error renaming file {0}", absoluteEntryTempFile), 'InstallPackage', pkg, err); +// zipfile.close(); +// return; +// } +// // Wait until output is done writing before reading the next zip entry. +// // Otherwise, it's possible to try to launch the .exe before it is done being created. +// zipfile.readEntry(); +// } else { +// try { +// await util.unlinkAsync(absoluteEntryTempFile); +// } catch (err) { +// // Ignore failure to delete temp file. We already have an error to return. +// } +// } +// }); + +// readStream.on('error', (err) => { +// // Don't call reject() a second time. +// if (!pendingError) { +// pendingError = new PackageManagerError('Error in readStream', localize("read.stream.error", 'Error in read stream'), 'InstallPackage', pkg, err); +// zipfile.close(); +// } +// }); + +// writeStream.on('error', (err) => { +// // Don't call reject() a second time. +// if (!pendingError) { +// pendingError = new PackageManagerError('Error in writeStream', localize("write.stream.error", 'Error in write stream'), 'InstallPackage', pkg, err); +// zipfile.close(); +// } +// }); + +// readStream.pipe(writeStream); +// }); +// }); +// } else { +// // Skip the message for text files, because there is a duplicate text file unzipped. +// if (path.extname(absoluteEntryPath) !== ".txt") { +// this.AppendLineChannel(localize("file.already.exists", "Warning: File '{0}' already exists and was not updated.", absoluteEntryPath)); +// } +// zipfile.readEntry(); +// } +// }); +// } +// }); + +// zipfile.readEntry(); +// }); +// }).then(() => { +// // Clean up temp file +// pkg.tmpFile.removeCallback(); +// }); +// } + +// private AppendChannel(text: string): void { +// if (this.outputChannel) { +// this.outputChannel.append(text); +// } +// } + +// private AppendLineChannel(text: string): void { +// if (this.outputChannel) { +// this.outputChannel.appendLine(text); +// } +// } +// } + +// export function VersionsMatch(pkg: IPackage, info: PlatformInformation): boolean { +// if (pkg.versionRegex) { +// // If we have a versionRegex but did not get a platformVersion +// if (!info.version) { +// // If we are expecting to match the versionRegex, return false since there was no version found. +// // +// // If we are expecting to not match the versionRegex, return true since we are expecting to +// // not match the version string, the only match would be if versionRegex was not set. +// return !pkg.matchVersion; +// } +// const regex: RegExp = new RegExp(pkg.versionRegex); + +// return (pkg.matchVersion ? +// regex.test(info.version) : +// !regex.test(info.version) +// ); +// } + +// // No versionRegex provided. +// return true; +// } + +// export function ArchitecturesMatch(value: IPackage, info: PlatformInformation): boolean { +// return !value.architectures || (value.architectures.indexOf(info.architecture) !== -1); +// } + +// export function PlatformsMatch(value: IPackage, info: PlatformInformation): boolean { +// return !value.platforms || value.platforms.indexOf(info.platform) !== -1; +// } From 2d4ef09350971aa02b4992fc4dc55130d6fd429c Mon Sep 17 00:00:00 2001 From: Colen Garoutte-Carson Date: Tue, 7 Dec 2021 16:40:28 -0800 Subject: [PATCH 02/15] Work in progress --- Extension/src/Debugger/attachToProcess.ts | 90 ++- .../Debugger/debugAdapterDescriptorFactory.ts | 24 +- Extension/src/LanguageServer/client.ts | 1 - Extension/src/LanguageServer/extension.ts | 88 +-- .../LanguageServer/timeTelemetryCollector.ts | 2 +- Extension/src/commands.ts | 104 ---- Extension/src/common.ts | 118 ---- Extension/src/installationInformation.ts | 38 -- Extension/src/main.ts | 447 +-------------- Extension/src/packageManager.ts | 530 ------------------ 10 files changed, 72 insertions(+), 1370 deletions(-) delete mode 100644 Extension/src/commands.ts delete mode 100644 Extension/src/installationInformation.ts delete mode 100644 Extension/src/packageManager.ts diff --git a/Extension/src/Debugger/attachToProcess.ts b/Extension/src/Debugger/attachToProcess.ts index d00cbe1697..a588869f39 100644 --- a/Extension/src/Debugger/attachToProcess.ts +++ b/Extension/src/Debugger/attachToProcess.ts @@ -26,11 +26,7 @@ export class AttachPicker { // We should not await on this function. public async ShowAttachEntries(): Promise { - // if (!await util.isExtensionReady()) { - // util.displayExtensionNotReadyPrompt(); - // } else { - return showQuickPick(() => this.attachItemsProvider.getAttachItems()); - // } + return showQuickPick(() => this.attachItemsProvider.getAttachItems()); } } @@ -42,65 +38,61 @@ export class RemoteAttachPicker { private _channel: vscode.OutputChannel; public async ShowAttachEntries(config: any): Promise { - // if (!await util.isExtensionReady()) { - // util.displayExtensionNotReadyPrompt(); - // } else { - this._channel.clear(); + this._channel.clear(); - const pipeTransport: any = config ? config.pipeTransport : undefined; + const pipeTransport: any = config ? config.pipeTransport : undefined; - if (!pipeTransport) { - throw new Error(localize("no.pipetransport", "Chosen debug configuration does not contain {0}", "pipeTransport")); - } + if (!pipeTransport) { + throw new Error(localize("no.pipetransport", "Chosen debug configuration does not contain {0}", "pipeTransport")); + } - let pipeProgram: string | undefined; + let pipeProgram: string | undefined; - if (os.platform() === 'win32' && - pipeTransport.pipeProgram && - !await util.checkFileExists(pipeTransport.pipeProgram)) { - const pipeProgramStr: string = pipeTransport.pipeProgram.toLowerCase().trim(); - const expectedArch: debugUtils.ArchType = debugUtils.ArchType[process.arch as keyof typeof debugUtils.ArchType]; + if (os.platform() === 'win32' && + pipeTransport.pipeProgram && + !await util.checkFileExists(pipeTransport.pipeProgram)) { + const pipeProgramStr: string = pipeTransport.pipeProgram.toLowerCase().trim(); + const expectedArch: debugUtils.ArchType = debugUtils.ArchType[process.arch as keyof typeof debugUtils.ArchType]; - // Check for pipeProgram - if (!await util.checkFileExists(config.pipeTransport.pipeProgram)) { - pipeProgram = debugUtils.ArchitectureReplacer.checkAndReplaceWSLPipeProgram(pipeProgramStr, expectedArch); - } + // Check for pipeProgram + if (!await util.checkFileExists(config.pipeTransport.pipeProgram)) { + pipeProgram = debugUtils.ArchitectureReplacer.checkAndReplaceWSLPipeProgram(pipeProgramStr, expectedArch); + } - // If pipeProgram does not get replaced and there is a pipeCwd, concatenate with pipeProgramStr and attempt to replace. - if (!pipeProgram && config.pipeTransport.pipeCwd) { - const pipeCwdStr: string = config.pipeTransport.pipeCwd.toLowerCase().trim(); - const newPipeProgramStr: string = path.join(pipeCwdStr, pipeProgramStr); + // If pipeProgram does not get replaced and there is a pipeCwd, concatenate with pipeProgramStr and attempt to replace. + if (!pipeProgram && config.pipeTransport.pipeCwd) { + const pipeCwdStr: string = config.pipeTransport.pipeCwd.toLowerCase().trim(); + const newPipeProgramStr: string = path.join(pipeCwdStr, pipeProgramStr); - if (!await util.checkFileExists(newPipeProgramStr)) { - pipeProgram = debugUtils.ArchitectureReplacer.checkAndReplaceWSLPipeProgram(newPipeProgramStr, expectedArch); - } + if (!await util.checkFileExists(newPipeProgramStr)) { + pipeProgram = debugUtils.ArchitectureReplacer.checkAndReplaceWSLPipeProgram(newPipeProgramStr, expectedArch); } } + } - if (!pipeProgram) { - pipeProgram = pipeTransport.pipeProgram; - } + if (!pipeProgram) { + pipeProgram = pipeTransport.pipeProgram; + } - const pipeArgs: string[] = pipeTransport.pipeArgs; + const pipeArgs: string[] = pipeTransport.pipeArgs; - const argList: string = RemoteAttachPicker.createArgumentList(pipeArgs); + const argList: string = RemoteAttachPicker.createArgumentList(pipeArgs); - const pipeCmd: string = `"${pipeProgram}" ${argList}`; + const pipeCmd: string = `"${pipeProgram}" ${argList}`; - const processes: AttachItem[]= await this.getRemoteOSAndProcesses(pipeCmd); - const attachPickOptions: vscode.QuickPickOptions = { - matchOnDetail: true, - matchOnDescription: true, - placeHolder: localize("select.process.attach", "Select the process to attach to") - }; + const processes: AttachItem[]= await this.getRemoteOSAndProcesses(pipeCmd); + const attachPickOptions: vscode.QuickPickOptions = { + matchOnDetail: true, + matchOnDescription: true, + placeHolder: localize("select.process.attach", "Select the process to attach to") + }; - const item: AttachItem | undefined = await vscode.window.showQuickPick(processes, attachPickOptions); - if (item) { - return item.id; - } else { - throw new Error(localize("process.not.selected", "Process not selected.")); - } - // } + const item: AttachItem | undefined = await vscode.window.showQuickPick(processes, attachPickOptions); + if (item) { + return item.id; + } else { + throw new Error(localize("process.not.selected", "Process not selected.")); + } } // Creates a string to run on the host machine which will execute a shell script on the remote machine to retrieve OS and processes diff --git a/Extension/src/Debugger/debugAdapterDescriptorFactory.ts b/Extension/src/Debugger/debugAdapterDescriptorFactory.ts index 6862ecb951..539d3d349f 100644 --- a/Extension/src/Debugger/debugAdapterDescriptorFactory.ts +++ b/Extension/src/Debugger/debugAdapterDescriptorFactory.ts @@ -4,7 +4,6 @@ * ------------------------------------------------------------------------------------------ */ import * as vscode from "vscode"; -//import * as util from '../common'; import * as path from 'path'; import * as os from 'os'; import * as nls from 'vscode-nls'; @@ -34,16 +33,11 @@ export class CppdbgDebugAdapterDescriptorFactory extends AbstractDebugAdapterDes } async createDebugAdapterDescriptor(session: vscode.DebugSession, executable?: vscode.DebugAdapterExecutable): Promise { - // if (await util.isExtensionReady()) { + const adapter: string = "./debugAdapters/bin/OpenDebugAD7" + (os.platform() === 'win32' ? ".exe" : ""); - const adapter: string = "./debugAdapters/bin/OpenDebugAD7" + (os.platform() === 'win32' ? ".exe" : ""); + const command: string = path.join(this.context.extensionPath, adapter); - const command: string = path.join(this.context.extensionPath, adapter); - - return new vscode.DebugAdapterExecutable(command, []); - // } else { - // throw new Error(util.extensionNotReadyString); - // } + return new vscode.DebugAdapterExecutable(command, []); } } @@ -59,14 +53,10 @@ export class CppvsdbgDebugAdapterDescriptorFactory extends AbstractDebugAdapterD vscode.window.showErrorMessage(localize("debugger.not.available", "Debugger type '{0}' is not avaliable for non-Windows machines.", "cppvsdbg")); return null; } else { - // if (await util.isExtensionReady()) { - return new vscode.DebugAdapterExecutable( - path.join(this.context.extensionPath, './debugAdapters/vsdbg/bin/vsdbg.exe'), - ['--interpreter=vscode', '--extConfigDir=%USERPROFILE%\\.cppvsdbg\\extensions'] - ); - // } else { - // throw new Error(util.extensionNotReadyString); - // } + return new vscode.DebugAdapterExecutable( + path.join(this.context.extensionPath, './debugAdapters/vsdbg/bin/vsdbg.exe'), + ['--interpreter=vscode', '--extConfigDir=%USERPROFILE%\\.cppvsdbg\\extensions'] + ); } } } diff --git a/Extension/src/LanguageServer/client.ts b/Extension/src/LanguageServer/client.ts index eb43232e9c..ee24098628 100644 --- a/Extension/src/LanguageServer/client.ts +++ b/Extension/src/LanguageServer/client.ts @@ -1481,7 +1481,6 @@ export class DefaultClient implements Client { experimentalFeatures: workspaceSettings.experimentalFeatures, edgeMessagesDirectory: path.join(util.getExtensionFilePath("bin"), "messages", util.getLocaleId()), localizedStrings: localizedStrings, - supportCuda: util.supportCuda, packageVersion: util.packageJson.version }, middleware: createProtocolFilter(allClients), diff --git a/Extension/src/LanguageServer/extension.ts b/Extension/src/LanguageServer/extension.ts index 8342d0da26..068756c2fb 100644 --- a/Extension/src/LanguageServer/extension.ts +++ b/Extension/src/LanguageServer/extension.ts @@ -15,7 +15,6 @@ import { UI, getUI } from './ui'; import { Client, openFileVersions } from './client'; import { ClientCollection } from './clientCollection'; import { CppSettings, OtherSettings } from './settings'; -//import { PersistentWorkspaceState, PersistentState } from './persistentState'; import { PersistentState } from './persistentState'; import { getLanguageConfig } from './languageConfig'; import { getCustomConfigProviders } from './customProviders'; @@ -24,7 +23,6 @@ import { Range } from 'vscode-languageclient'; import { ChildProcess, spawn } from 'child_process'; import { getTargetBuildInfo, BuildInfo } from '../githubAPI'; import { PackageVersion } from '../packageVersion'; -//import { getTemporaryCommandRegistrarInstance } from '../commands'; import * as rd from 'readline'; import * as yauzl from 'yauzl'; import { Readable, Writable } from 'stream'; @@ -47,9 +45,6 @@ let intervalTimer: NodeJS.Timer; let insiderUpdateEnabled: boolean = false; let insiderUpdateTimer: NodeJS.Timer; const insiderUpdateTimerInterval: number = 1000 * 60 * 60; -//let realActivationOccurred: boolean = false; -//let tempCommands: vscode.Disposable[] = []; -//let activatedPreviously: PersistentWorkspaceState; let buildInfoCache: BuildInfo | undefined; const cppInstallVsixStr: string = 'C/C++: Install vsix -- '; let taskProvider: vscode.Disposable; @@ -171,42 +166,18 @@ function sendActivationTelemetry(): void { /** * activate: set up the extension for language services */ -export async function activate(activationEventOccurred: boolean): Promise { - // if (realActivationOccurred) { - // return; // Occurs if multiple delayed commands occur before the real commands are registered. - // } - - // // Activate immediately if an activation event occurred in the previous workspace session. - // // If onActivationEvent doesn't occur, it won't auto-activate next time. - // activatedPreviously = new PersistentWorkspaceState("activatedPreviously", false); - // if (activatedPreviously.Value) { - // activatedPreviously.Value = false; - // realActivation(); - // } - - //if (tempCommands.length === 0) { // Only needs to be added once. - // tempCommands.push(vscode.workspace.onDidOpenTextDocument(onDidOpenTextDocument)); - //} - - // handle "workspaceContains:/.vscode/c_cpp_properties.json" activation event. - //let cppPropertiesExists: boolean = false; +export async function activate(): Promise { + if (vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length > 0) { for (let i: number = 0; i < vscode.workspace.workspaceFolders.length; ++i) { const config: string = path.join(vscode.workspace.workspaceFolders[i].uri.fsPath, ".vscode/c_cpp_properties.json"); if (await util.checkFileExists(config)) { - //cppPropertiesExists = true; const doc: vscode.TextDocument = await vscode.workspace.openTextDocument(config); vscode.languages.setTextDocumentLanguage(doc, "jsonc"); } } } - // // Check if an activation event has already occurred. - // if (activationEventOccurred) { - // onActivationEvent(); - // return; - // } - taskProvider = vscode.tasks.registerTaskProvider(CppBuildTaskProvider.CppBuildScriptType, cppBuildTaskProvider); vscode.tasks.onDidStartTask(event => { @@ -267,48 +238,6 @@ export async function activate(activationEventOccurred: boolean): Promise } }); - // if (cppPropertiesExists) { - // onActivationEvent(); - // return; - // } - - // // handle "onLanguage:c", "onLanguage:cpp" and "onLanguage:cuda-cpp" activation events. - // if (vscode.workspace.textDocuments !== undefined && vscode.workspace.textDocuments.length > 0) { - // for (let i: number = 0; i < vscode.workspace.textDocuments.length; ++i) { - // const document: vscode.TextDocument = vscode.workspace.textDocuments[i]; - // if (document.uri.scheme === "file") { - // if (document.languageId === "c" || document.languageId === "cpp" || document.languageId === "cuda-cpp") { - // onActivationEvent(); - // return; - // } - // } - // } - // } -//} - -// function onDidOpenTextDocument(document: vscode.TextDocument): void { -// if (document.languageId === "c" || document.languageId === "cpp" || document.languageId === "cuda-cpp") { -// onActivationEvent(); -// } -// } - -// function onActivationEvent(): void { -// if (tempCommands.length === 0) { -// return; -// } -// -// // Cancel all the temp commands that just look for activations. -// tempCommands.forEach((command) => { -// command.dispose(); -// }); -// tempCommands = []; -// if (!realActivationOccurred) { -// realActivation(); -// } -// activatedPreviously.Value = true; -// } - -//function realActivation(): void { if (new CppSettings((vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length > 0) ? vscode.workspace.workspaceFolders[0]?.uri : undefined).intelliSenseEngine === "Disabled") { throw new Error(intelliSenseDisabledError); } else { @@ -325,7 +254,6 @@ export async function activate(activationEventOccurred: boolean): Promise } } - //realActivationOccurred = true; console.log("starting language server"); clients = new ClientCollection(); ui = getUI(); @@ -793,7 +721,6 @@ export function registerCommands(): void { } commandsRegistered = true; - //getTemporaryCommandRegistrarInstance().clearTempCommands(); disposables.push(vscode.commands.registerCommand('C_Cpp.SwitchHeaderSource', onSwitchHeaderSource)); disposables.push(vscode.commands.registerCommand('C_Cpp.ResetDatabase', onResetDatabase)); disposables.push(vscode.commands.registerCommand('C_Cpp.ConfigurationSelect', onSelectConfiguration)); @@ -834,8 +761,6 @@ export function registerCommands(): void { disposables.push(vscode.commands.registerCommand('cpptools.activeConfigCustomVariable', onGetActiveConfigCustomVariable)); disposables.push(vscode.commands.registerCommand('cpptools.setActiveConfigName', onSetActiveConfigName)); disposables.push(vscode.commands.registerCommand('C_Cpp.RestartIntelliSenseForFile', onRestartIntelliSenseForFile)); - - //getTemporaryCommandRegistrarInstance().executeDelayedCommands(); } function onRestartIntelliSenseForFile(): void { @@ -1315,9 +1240,6 @@ function handleMacCrashFileRead(err: NodeJS.ErrnoException | undefined | null, d } export function deactivate(): Thenable { - // if (!realActivationOccurred) { - // return Promise.resolve(); - // } clients.timeTelemetryCollector.clear(); console.log("deactivating extension"); telemetry.logLanguageServerEvent("LanguageServerShutdown"); @@ -1340,15 +1262,9 @@ export function isFolderOpen(): boolean { } export function getClients(): ClientCollection { - // if (!realActivationOccurred) { - // realActivation(); - // } return clients; } export function getActiveClient(): Client { - // if (!realActivationOccurred) { - // realActivation(); - // } return clients.ActiveClient; } diff --git a/Extension/src/LanguageServer/timeTelemetryCollector.ts b/Extension/src/LanguageServer/timeTelemetryCollector.ts index 970fe8291a..17ede8149e 100644 --- a/Extension/src/LanguageServer/timeTelemetryCollector.ts +++ b/Extension/src/LanguageServer/timeTelemetryCollector.ts @@ -7,7 +7,7 @@ import * as util from '../common'; import * as vscode from 'vscode'; interface TimeStampSequence { - firstFile?: number; // when the extension is activated by realActivation. Defined only for "cold" start cases. + firstFile?: number; // when the extension is activated. Defined only for "cold" start cases. didOpen: number; // when the file appears in the editor. Defined for "warm" start cases. setup: number; // when the Intellisense_client constructor is completed updateRange: number; // when publishDiagnostics & provideSemanticTokens is completed diff --git a/Extension/src/commands.ts b/Extension/src/commands.ts deleted file mode 100644 index 03d25c48a5..0000000000 --- a/Extension/src/commands.ts +++ /dev/null @@ -1,104 +0,0 @@ -// /* -------------------------------------------------------------------------------------------- -// * Copyright (c) Microsoft Corporation. All Rights Reserved. -// * See 'LICENSE' in the project root for license information. -// * ------------------------------------------------------------------------------------------ */ -// 'use strict'; - -// import * as vscode from 'vscode'; -// import * as LanguageServer from './LanguageServer/extension'; -// import * as util from './common'; -// import * as nls from 'vscode-nls'; - -// nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })(); -// const localize: nls.LocalizeFunc = nls.loadMessageBundle(); - -// class TemporaryCommandRegistrar { -// // Used to save/re-execute commands used before the extension has activated (e.g. delayed by dependency downloading). -// private delayedCommandsToExecute: Set; -// private tempCommands: vscode.Disposable[]; // Need to save this to unregister/dispose the temporary commands. -// private isLanguageServerDisabled: boolean = false; -// private isActivationReady: boolean = false; - -// private commandsToRegister: string[] = [ -// "C_Cpp.ConfigurationEditJSON", -// "C_Cpp.ConfigurationEditUI", -// "C_Cpp.ConfigurationSelect", -// "C_Cpp.ConfigurationProviderSelect", -// "C_Cpp.SwitchHeaderSource", -// "C_Cpp.EnableErrorSquiggles", -// "C_Cpp.DisableErrorSquiggles", -// "C_Cpp.ToggleIncludeFallback", -// "C_Cpp.ToggleDimInactiveRegions", -// "C_Cpp.ResetDatabase", -// "C_Cpp.TakeSurvey", -// "C_Cpp.LogDiagnostics", -// "C_Cpp.RescanWorkspace", -// "C_Cpp.GenerateEditorConfig", -// "C_Cpp.VcpkgClipboardInstallSuggested", -// "C_Cpp.VcpkgOnlineHelpSuggested", -// "C_Cpp.CheckForCompiler", -// "C_Cpp.RunCodeAnalysisOnActiveFile", -// "C_Cpp.RunCodeAnalysisOnOpenFiles", -// "C_Cpp.RunCodeAnalysisOnAllFiles", -// "C_Cpp.ClearCodeAnalysisSquiggles" -// ]; - -// constructor() { -// this.tempCommands = []; -// this.delayedCommandsToExecute = new Set(); - -// // Add temp commands that invoke the real commands after download/install is complete (preventing an error message) -// if (util.extensionContext) { -// this.commandsToRegister.forEach(command => { -// this.registerTempCommand(command); -// }); -// } -// } - -// public registerTempCommand(command: string): void { -// this.tempCommands.push(vscode.commands.registerCommand(command, () => { -// if (this.isLanguageServerDisabled) { -// vscode.window.showInformationMessage(localize("command.disabled", 'This command is disabled because "{0}" is set to "{1}".', "C_Cpp.intelliSenseEngine", "Disabled")); -// return; -// } -// this.delayedCommandsToExecute.add(command); -// if (this.isActivationReady) { -// LanguageServer.activate(true); -// } -// })); -// } - -// public disableLanguageServer(): void { -// this.isLanguageServerDisabled = true; -// } - -// public activateLanguageServer(): void { -// // Main activation code. -// LanguageServer.activate(this.delayedCommandsToExecute.size > 0); -// this.isActivationReady = true; -// } - -// public clearTempCommands(): void { -// this.tempCommands.forEach((command) => { -// command.dispose(); -// }); -// this.tempCommands = []; -// } - -// public executeDelayedCommands(): void { -// this.delayedCommandsToExecute.forEach((command) => { -// vscode.commands.executeCommand(command); -// }); -// this.delayedCommandsToExecute.clear(); -// } -// } - -// // let tempCommandRegistrar: TemporaryCommandRegistrar; - -// // export function initializeTemporaryCommandRegistrar(): void { -// // tempCommandRegistrar = new TemporaryCommandRegistrar(); -// // } - -// // export function getTemporaryCommandRegistrarInstance(): TemporaryCommandRegistrar { -// // return tempCommandRegistrar; -// // } diff --git a/Extension/src/common.ts b/Extension/src/common.ts index 50d8beb4f0..503ac03796 100644 --- a/Extension/src/common.ts +++ b/Extension/src/common.ts @@ -20,13 +20,11 @@ import { ClientRequest, OutgoingHttpHeaders } from 'http'; import { lookupString } from './nativeStrings'; import * as nls from 'vscode-nls'; import { Readable } from 'stream'; -//import { PackageManager, IPackage } from './packageManager'; 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 let supportCuda: boolean = false; export type Mutable = { // eslint-disable-next-line @typescript-eslint/array-type @@ -174,13 +172,6 @@ export function isHeader(uri: vscode.Uri): boolean { return !ext || ext.startsWith(".h") || ext.startsWith(".H"); } -// // Extension is ready if install.lock exists and debugAdapters folder exist. -// export async function isExtensionReady(): Promise { -// const doesInstallLockFileExist: boolean = await checkInstallLockFile(); -// -// return doesInstallLockFileExist; -// } - let isExtensionNotReadyPromptDisplayed: boolean = false; export const extensionNotReadyString: string = localize("extension.not.ready", 'The C/C++ extension is still installing. See the output window for more information.'); @@ -425,32 +416,6 @@ export function getHttpsProxyAgent(): HttpsProxyAgent | undefined { return new HttpsProxyAgent(proxyOptions); } -// export interface InstallLockContents { -// platform: string; -// architecture: string; -// }; - -// export function touchInstallLockFile(info: PlatformInformation): Promise { -// const installLockObject: InstallLockContents = { -// platform: info.platform, -// architecture: info.architecture -// }; -// const content: string = JSON.stringify(installLockObject); -// return writeFileText(getInstallLockPath(), content); -// } - -export function touchExtensionFolder(): Promise { - return new Promise((resolve, reject) => { - fs.utimes(path.resolve(extensionPath, ".."), new Date(Date.now()), new Date(Date.now()), (err) => { - if (err) { - reject(err); - } - - resolve(); - }); - }); -} - /** Test whether a file exists */ export function checkFileExists(filePath: string): Promise { return new Promise((resolve, reject) => { @@ -529,84 +494,6 @@ export function readDir(dirPath: string): Promise { }); } -// /** Test whether the lock file exists.*/ -// export function checkInstallLockFile(): Promise { -// return checkFileExists(getInstallLockPath()); -// } - -// /** Check if the core binaries exists in extension's installation folder */ -// export async function checkInstallBinariesExist(): Promise { -// if (!checkInstallLockFile()) { -// return false; -// } -// let installBinariesExist: boolean = true; -// const info: PlatformInformation = await PlatformInformation.GetPlatformInformation(); -// const packageManager: PackageManager = new PackageManager(info); -// const packages: Promise = packageManager.GetPackages(); -// for (const pkg of await packages) { -// if (pkg.binaries) { -// await Promise.all(pkg.binaries.map(async (file: string) => { -// if (!await checkFileExists(file)) { -// installBinariesExist = false; -// const fileBase: string = path.basename(file); -// console.log(`Extension file ${fileBase} is missing.`); -// Telemetry.logLanguageServerEvent("missingBinary", { "source": `${fileBase}` }); -// } -// })); -// } -// } -// return installBinariesExist; -// } - -// /** Check if the core Json files exists in extension's installation folder */ -// export async function checkInstallJsonsExist(): Promise { -// let installJsonsExist: boolean = true; -// const jsonFiles: string[] = [ -// "bin/common.json", -// "bin/linux.clang.arm.json", -// "bin/linux.clang.arm64.json", -// "bin/linux.clang.x64.json", -// "bin/linux.clang.x86.json", -// "bin/linux.gcc.arm.json", -// "bin/linux.gcc.arm64.json", -// "bin/linux.gcc.x64.json", -// "bin/linux.gcc.x86.json", -// "bin/macos.clang.arm.json", -// "bin/macos.clang.arm64.json", -// "bin/macos.clang.x64.json", -// "bin/macos.clang.x86.json", -// "bin/macos.gcc.arm.json", -// "bin/macos.gcc.arm64.json", -// "bin/macos.gcc.x64.json", -// "bin/macos.gcc.x86.json", -// "bin/windows.clang.arm.json", -// "bin/windows.clang.arm64.json", -// "bin/windows.clang.x64.json", -// "bin/windows.clang.x86.json", -// "bin/windows.gcc.arm.json", -// "bin/windows.gcc.arm64.json", -// "bin/windows.gcc.x64.json", -// "bin/windows.gcc.x86.json", -// "bin/windows.msvc.arm.json", -// "bin/windows.msvc.arm64.json", -// "bin/windows.msvc.x64.json", -// "bin/windows.msvc.x86.json", -// "debugAdapters/bin/cppdbg.ad7Engine.json" -// ]; -// await Promise.all(jsonFiles.map(async (file) => { -// if (!await checkFileExists(path.join(extensionPath, file))) { -// installJsonsExist = false; -// console.log(`Extension file ${file} is missing.`); -// Telemetry.logLanguageServerEvent("missingJson", { "source": `${file}` }); -// } -// })); -// return installJsonsExist; -// } - -// export async function removeInstallLockFile(): Promise { -// await unlinkAsync(path.join(extensionPath, "install.lock")); -// } - /** Reads the content of a text file */ export function readFileText(filePath: string, encoding: string = "utf8"): Promise { return new Promise((resolve, reject) => { @@ -661,11 +548,6 @@ export function deleteFile(filePath: string): Promise { }); } -// // Get the path of the lock file. This is used to indicate that the platform-specific dependencies have been downloaded. -// export function getInstallLockPath(): string { -// return getExtensionFilePath("install.lock"); -// } - export function getReadmeMessage(): string { const readmePath: string = getExtensionFilePath("README.md"); const readmeMessage: string = localize("refer.read.me", "Please refer to {0} for troubleshooting information. Issues can be created at {1}", readmePath, "https://github.com/Microsoft/vscode-cpptools/issues"); diff --git a/Extension/src/installationInformation.ts b/Extension/src/installationInformation.ts deleted file mode 100644 index 0a3244bdfe..0000000000 --- a/Extension/src/installationInformation.ts +++ /dev/null @@ -1,38 +0,0 @@ -// /* -------------------------------------------------------------------------------------------- -// * Copyright (c) Microsoft Corporation. All Rights Reserved. -// * See 'LICENSE' in the project root for license information. -// * ------------------------------------------------------------------------------------------ */ - -// export enum InstallationType { -// Online, -// Offline -// } - -// export class InstallationInformation { -// stage?: string; -// type?: InstallationType; -// hasError: boolean; -// telemetryProperties: { [key: string]: string }; - -// constructor() { -// this.hasError = false; -// this.telemetryProperties = {}; -// } -// } - -// let installBlob: InstallationInformation; - -// export function getInstallationInformation(): InstallationInformation { -// if (!installBlob) { -// installBlob = new InstallationInformation(); -// } -// return installBlob; -// } - -// export function setInstallationStage(stage: string): void { -// getInstallationInformation().stage = stage; -// } - -// export function setInstallationType(type: InstallationType): void { -// getInstallationInformation().type = type; -// } diff --git a/Extension/src/main.ts b/Extension/src/main.ts index 78549bceae..15ed3f31a0 100644 --- a/Extension/src/main.ts +++ b/Extension/src/main.ts @@ -5,30 +5,17 @@ 'use strict'; import * as DebuggerExtension from './Debugger/extension'; -//import * as fs from 'fs'; import * as LanguageServer from './LanguageServer/extension'; import * as os from 'os'; import * as path from 'path'; import * as Telemetry from './telemetry'; import * as util from './common'; import * as vscode from 'vscode'; -import * as nls from 'vscode-nls'; -//import { PersistentState } from './LanguageServer/persistentState'; import { CppToolsApi, CppToolsExtension } from 'vscode-cpptools'; -//import { getTemporaryCommandRegistrarInstance, initializeTemporaryCommandRegistrar } from './commands'; -//import { PlatformInformation, GetOSName } from './platform'; import { PlatformInformation } from './platform'; -//import { PackageManager, PackageManagerError, IPackage, VersionsMatch, ArchitecturesMatch, PlatformsMatch } from './packageManager'; -//import { getInstallationInformation, InstallationInformation, setInstallationStage, setInstallationType, InstallationType } from './installationInformation'; -//import { Logger, getOutputChannelLogger, showOutputChannel } from './logger'; -//import { CppTools1, NullCppTools } from './cppTools1'; import { CppTools1 } from './cppTools1'; import { CppSettings } from './LanguageServer/settings'; -//import { vsixNameForPlatform, releaseDownloadUrl } from './githubAPI'; - -nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })(); -const localize: nls.LocalizeFunc = nls.loadMessageBundle(); const cppTools: CppTools1 = new CppTools1(); let languageServiceDisabled: boolean = false; @@ -36,20 +23,7 @@ let reloadMessageShown: boolean = false; const disposables: vscode.Disposable[] = []; export async function activate(context: vscode.ExtensionContext): Promise { - // let errMsg: string = ""; - // const arch: string = PlatformInformation.GetArchitecture(); - // if (arch !== 'x64' && (process.platform !== 'win32' || (arch !== 'x86' && arch !== 'arm64')) && ((process.platform === 'win32' || process.platform === 'darwin') || (arch !== 'arm' && arch !== 'arm64')) && (process.platform !== 'darwin' || arch !== 'arm64')) { - // errMsg = localize("architecture.not.supported", "Architecture {0} is not supported. ", String(arch)); - // } else if (process.platform === 'linux' && await util.checkDirectoryExists('/etc/alpine-release')) { - // errMsg = localize("apline.containers.not.supported", "Alpine containers are not supported."); - // } - // if (errMsg) { - // vscode.window.showErrorMessage(errMsg); - // return new NullCppTools(); - // } - util.setExtensionContext(context); - //initializeTemporaryCommandRegistrar(); Telemetry.activate(); util.setProgress(0); @@ -73,25 +47,16 @@ export async function activate(context: vscode.ExtensionContext): Promise 0) ? vscode.workspace.workspaceFolders[0]?.uri : undefined); if (settings.intelliSenseEngine === "Disabled") { languageServiceDisabled = true; - //getTemporaryCommandRegistrarInstance().disableLanguageServer(); disposables.push(vscode.workspace.onDidChangeConfiguration(() => { if (!reloadMessageShown && settings.intelliSenseEngine !== "Disabled") { reloadMessageShown = true; @@ -106,62 +71,7 @@ export async function activate(context: vscode.ExtensionContext): PromiseJSON.parse(fileContents); - // } catch (error) { - // // If the contents of install.lock are corrupted, treat as if it's empty. - // } - // } - // - // // Check the main binaries files to declare if the extension has been installed successfully. - // if (process.platform !== installedPlatformAndArchitecture.platform - // || (arch !== installedPlatformAndArchitecture.architecture - // && !(process.platform === "win32" - // // On x64 Windows, allow x86 binaries. - // && ((arch === "x64" && installedPlatformAndArchitecture.architecture === "x86") - // // On arm64 Windows, allow x86 or x64 binaries. - // || (arch === "arm64" && ((installedPlatformAndArchitecture.architecture === "x86") || (installedPlatformAndArchitecture.architecture === "x64"))))) - // // On arm64 macOS, allow x64 binaries. - // && !(process.platform === "darwin" && arch === "arm64" && installedPlatformAndArchitecture.architecture === "x64"))) { - // // Check if the correct offline/insiders vsix is installed on the correct platform. - // const platformInfo: PlatformInformation = await PlatformInformation.GetPlatformInformation(); - // const vsixName: string = vsixNameForPlatform(platformInfo); - // const downloadLink: string = localize("download.button", "Go to Download Page"); - // errMsg = localize("native.binaries.not.supported", "This {0} {1} version of the extension is incompatible with your OS. Please download and install the \"{2}\" version of the extension.", GetOSName(installedPlatformAndArchitecture.platform), installedPlatformAndArchitecture.architecture, vsixName); - // vscode.window.showErrorMessage(errMsg, downloadLink).then(async (selection) => { - // if (selection === downloadLink) { - // vscode.env.openExternal(vscode.Uri.parse(releaseDownloadUrl)); - // } - // }); - // } else if (!(await util.checkInstallBinariesExist())) { - // errMsg = localize("extension.installation.failed", "The C/C++ extension failed to install successfully. You will need to repair or reinstall the extension for C/C++ language features to function properly."); - // const reload: string = localize("remove.extension", "Attempt to Repair"); - // vscode.window.showErrorMessage(errMsg, reload).then(async (value?: string) => { - // if (value === reload) { - // await util.removeInstallLockFile(); - // vscode.commands.executeCommand("workbench.action.reloadWindow"); - // } - // }); - // } else if (!(await util.checkInstallJsonsExist())) { - // // Check the Json files to declare if the extension has been installed successfully. - // errMsg = localize("json.files.missing", "The C/C++ extension failed to install successfully. You will need to reinstall the extension for C/C++ language features to function properly."); - // const downloadLink: string = localize("download.button", "Go to Download Page"); - // vscode.window.showErrorMessage(errMsg, downloadLink).then(async (selection) => { - // if (selection === downloadLink) { - // vscode.env.openExternal(vscode.Uri.parse(releaseDownloadUrl)); - // } - // }); - // } - + LanguageServer.activate(); return cppTools; } @@ -176,353 +86,38 @@ export function deactivate(): Thenable { return LanguageServer.deactivate(); } -// async function processRuntimeDependencies(): Promise { -// const installLockExists: boolean = await util.checkInstallLockFile(); - -// setInstallationStage('getPlatformInfo'); -// const info: PlatformInformation = await PlatformInformation.GetPlatformInformation(); - -// let forceOnlineInstall: boolean = false; -// if (info.platform === "darwin" && info.version) { -// const darwinVersion: PersistentState = new PersistentState("Cpp.darwinVersion", info.version); - -// // macOS version has changed -// if (darwinVersion.Value !== info.version) { -// const highSierraOrLowerRegex: RegExp = new RegExp('10\\.(1[0-3]|[0-9])(\\..*)*$'); -// const lldbMiFolderPath: string = util.getExtensionFilePath('./debugAdapters/lldb-mi'); - -// // For macOS and if a user has upgraded their OS, check to see if we are on Mojave or later -// // and that the debugAdapters/lldb-mi folder exists. This will force a online install to get the correct binaries. -// if (!highSierraOrLowerRegex.test(info.version) && -// !await util.checkDirectoryExists(lldbMiFolderPath)) { - -// forceOnlineInstall = true; - -// setInstallationStage('cleanUpUnusedBinaries'); -// await cleanUpUnusedBinaries(info); -// } -// } -// } - -// const doOfflineInstall: boolean = installLockExists && !forceOnlineInstall; - -// if (doOfflineInstall) { -// // Offline Scenario: Lock file exists but package.json has not had its activationEvents rewritten. -// if (util.packageJson.activationEvents && util.packageJson.activationEvents.length === 1) { -// try { -// await offlineInstallation(info); -// } catch (error) { -// getOutputChannelLogger().showErrorMessage(localize('initialization.failed', 'The installation of the C/C++ extension failed. Please see the output window for more information.')); -// showOutputChannel(); - -// // Send the failure telemetry since postInstall will not be called. -// sendTelemetry(info); -// } -// } else { -// // The extension has been installed and activated before. -// await finalizeExtensionActivation(); -// } -// } else { -// // No lock file, need to download and install dependencies. -// try { -// await onlineInstallation(info); -// } catch (errJS) { -// const error: Error = errJS as Error; -// handleError(error); - -// // Send the failure telemetry since postInstall will not be called. -// sendTelemetry(info); -// } -// } -// } - -// async function offlineInstallation(info: PlatformInformation): Promise { -// setInstallationType(InstallationType.Offline); - -// setInstallationStage('cleanUpUnusedBinaries'); -// await cleanUpUnusedBinaries(info); - -// setInstallationStage('makeOfflineBinariesExecutable'); -// await makeOfflineBinariesExecutable(info); - -// setInstallationStage('rewriteManifest'); -// await rewriteManifest(); - -// setInstallationStage('postInstall'); -// await postInstall(info); -// } - -// async function onlineInstallation(info: PlatformInformation): Promise { -// setInstallationType(InstallationType.Online); - -// await downloadAndInstallPackages(info); - -// setInstallationStage('rewriteManifest'); -// await rewriteManifest(); - -// setInstallationStage('touchInstallLockFile'); -// await touchInstallLockFile(info); - -// setInstallationStage('postInstall'); -// await postInstall(info); -// } - -// async function downloadAndInstallPackages(info: PlatformInformation): Promise { -// const outputChannelLogger: Logger = getOutputChannelLogger(); -// outputChannelLogger.appendLine(localize("updating.dependencies", "Updating C/C++ dependencies...")); - -// const packageManager: PackageManager = new PackageManager(info, outputChannelLogger); - -// return vscode.window.withProgress({ -// location: vscode.ProgressLocation.Notification, -// cancellable: false -// }, async (progress, token) => { - -// progress.report({ message: "C/C++ Extension" , increment: 0}); -// outputChannelLogger.appendLine(''); -// setInstallationStage('downloadPackages'); -// await packageManager.DownloadPackages(progress); - -// outputChannelLogger.appendLine(''); -// setInstallationStage('installPackages'); -// await packageManager.InstallPackages(progress); -// }); -// } - -// function packageMatchesPlatform(pkg: IPackage, info: PlatformInformation): boolean { -// return PlatformsMatch(pkg, info) && -// (pkg.architectures === undefined || ArchitecturesMatch(pkg, info)) && -// VersionsMatch(pkg, info); -// } - -// function invalidPackageVersion(pkg: IPackage, info: PlatformInformation): boolean { -// return PlatformsMatch(pkg, info) && -// (pkg.architectures === undefined || ArchitecturesMatch(pkg, info)) && -// !VersionsMatch(pkg, info); -// } - -async function makeBinariesExecutable(info: PlatformInformation): Promise { - +async function makeBinariesExecutable(): Promise { + const promises: Thenable[] = []; if (process.platform !== 'win32') { - const binaries: string[] = [ + const commonBinaries: string[] = [ "./bin/cpptools", "./bin/cpptools-srv", "./LLVM/bin/clang-format", "./LLVM/bin/clang-tidy", + "./debugAdapters/bin/OpenDebugAD7" ]; - packages.forEach(p => { - if (p.binaries && p.binaries.length > 0 && - packageMatchesPlatform(p, info)) { - p.binaries.forEach(binary => promises.push(util.allowExecution(util.getExtensionFilePath(binary)))); - } - }); + commonBinaries.forEach(binary => promises.push(util.allowExecution(util.getExtensionFilePath(binary)))); + if (process.platform === "darwin") { + const macBinaries: string[] = [ + "./debugAdapters/lldb-mi/bin/lldb-mi", + "./debugAdapters/lldb/bin/debugserver", + "./debugAdapters/lldb/bin/lldb-mi", + "./debugAdapters/lldb/bin/lldb-argdumper", + "./debugAdapters/lldb/bin/lldb-launcher" + ]; + macBinaries.forEach(binary => promises.push(util.allowExecution(util.getExtensionFilePath(binary)))); + } } - - // const promises: Thenable[] = []; - // const packages: IPackage[] = util.packageJson["runtimeDependencies"]; - // packages.forEach(p => { - // if (p.binaries && p.binaries.length > 0 && - // packageMatchesPlatform(p, info)) { - // p.binaries.forEach(binary => promises.push(util.allowExecution(util.getExtensionFilePath(binary)))); - // } - // }); - // await Promise.all(promises); + await Promise.all(promises); } -// async function cleanUpUnusedBinaries(info: PlatformInformation): Promise { -// const promises: Thenable[] = []; -// const packages: IPackage[] = util.packageJson["runtimeDependencies"]; -// const logger: Logger = getOutputChannelLogger(); - -// packages.forEach(p => { -// if (p.binaries && p.binaries.length > 0 && -// invalidPackageVersion(p, info)) { -// p.binaries.forEach(binary => { -// const path: string = util.getExtensionFilePath(binary); -// if (fs.existsSync(path)) { -// logger.appendLine(`deleting: ${path}`); -// promises.push(util.deleteFile(path)); -// } -// }); -// } -// }); -// await Promise.all(promises); -// } - -// function touchInstallLockFile(info: PlatformInformation): Promise { -// return util.touchInstallLockFile(info); -// } - -// function handleError(error: Error): void { -// const installationInformation: InstallationInformation = getInstallationInformation(); -// installationInformation.hasError = true; -// installationInformation.telemetryProperties['stage'] = installationInformation.stage ?? ""; -// let errorMessage: string; - -// if (error instanceof PackageManagerError) { -// const packageError: PackageManagerError = error; - -// installationInformation.telemetryProperties['error.methodName'] = packageError.methodName; -// installationInformation.telemetryProperties['error.message'] = packageError.message; - -// if (packageError.innerError) { -// errorMessage = packageError.innerError.toString(); -// installationInformation.telemetryProperties['error.innerError'] = util.removePotentialPII(errorMessage); -// } else { -// errorMessage = packageError.localizedMessageText; -// } - -// if (packageError.pkg) { -// installationInformation.telemetryProperties['error.packageName'] = packageError.pkg.description; -// installationInformation.telemetryProperties['error.packageUrl'] = packageError.pkg.url; -// } - -// if (packageError.errorCode) { -// installationInformation.telemetryProperties['error.errorCode'] = util.removePotentialPII(packageError.errorCode); -// } -// } else { -// errorMessage = error.toString(); -// installationInformation.telemetryProperties['error.toString'] = util.removePotentialPII(errorMessage); -// } - -// const outputChannelLogger: Logger = getOutputChannelLogger(); -// if (installationInformation.stage === 'downloadPackages') { -// outputChannelLogger.appendLine(""); -// } -// // Show the actual message and not the sanitized one -// outputChannelLogger.appendLine(localize('failed.at.stage', "Failed at stage: {0}", installationInformation.stage)); -// outputChannelLogger.appendLine(errorMessage); -// outputChannelLogger.appendLine(""); -// outputChannelLogger.appendLine(localize('failed.at.stage2', 'If you work in an offline environment or repeatedly see this error, try downloading a version of the extension with all the dependencies pre-included from {0}, then use the "Install from VSIX" command in VS Code to install it.', releaseDownloadUrl)); -// showOutputChannel(); -// } - -function sendTelemetry(info: PlatformInformation): boolean { - let telemetryProperties: { [key: string]: string } = {}; - - //const installBlob: InstallationInformation = getInstallationInformation(); - const success: boolean = true;//!installBlob.hasError; - - telemetryProperties['success'] = success.toString(); - //telemetryProperties['type'] = installBlob.type === InstallationType.Online ? "online" : "offline"; - +function sendTelemetry(info: PlatformInformation): void { + const telemetryProperties: { [key: string]: string } = {}; if (info.distribution) { telemetryProperties['linuxDistroName'] = info.distribution.name; telemetryProperties['linuxDistroVersion'] = info.distribution.version; } - - // if (success) { - // util.setProgress(util.getProgressInstallSuccess()); - // } - telemetryProperties['osArchitecture'] = os.arch(); telemetryProperties['infoArchitecture'] = info.architecture; - Telemetry.logDebuggerEvent("acquisition", telemetryProperties); - - return success; } - -// async function postInstall(info: PlatformInformation): Promise { -// const outputChannelLogger: Logger = getOutputChannelLogger(); -// outputChannelLogger.appendLine(""); -// outputChannelLogger.appendLine(localize('finished.installing.dependencies', "Finished installing dependencies")); -// outputChannelLogger.appendLine(""); - -// const installSuccess: boolean = sendTelemetry(info); - -// // If there is a download failure, we shouldn't continue activating the extension in some broken state. -// if (!installSuccess) { -// throw new Error(localize("failed.installing.dependencies", "Failed installing dependencies")); -// } else { -// // Notify users if debugging may not be supported on their OS. -// util.checkDistro(info); - -// return finalizeExtensionActivation(); -// } -// } - -// async function finalizeExtensionActivation(): Promise { -// const settings: CppSettings = new CppSettings((vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length > 0) ? vscode.workspace.workspaceFolders[0]?.uri : undefined); -// if (settings.intelliSenseEngine === "Disabled") { -// languageServiceDisabled = true; -// //getTemporaryCommandRegistrarInstance().disableLanguageServer(); -// disposables.push(vscode.workspace.onDidChangeConfiguration(() => { -// if (!reloadMessageShown && settings.intelliSenseEngine !== "Disabled") { -// reloadMessageShown = true; -// util.promptForReloadWindowDueToSettingsChange(); -// } -// })); -// return; -// } -// disposables.push(vscode.workspace.onDidChangeConfiguration(() => { -// if (!reloadMessageShown && settings.intelliSenseEngine === "Disabled") { -// reloadMessageShown = true; -// util.promptForReloadWindowDueToSettingsChange(); -// } -// })); -// //getTemporaryCommandRegistrarInstance().activateLanguageServer(); -// } - -// function rewriteManifest(): Promise { -// // Replace activationEvents with the events that the extension should be activated for subsequent sessions. -// const packageJson: any = util.getRawPackageJson(); - -// packageJson.activationEvents = [ -// "onLanguage:c", -// "onLanguage:cpp", -// "onLanguage:cuda-cpp", -// "onCommand:extension.pickNativeProcess", -// "onCommand:extension.pickRemoteNativeProcess", -// "onCommand:C_Cpp.BuildAndDebugActiveFile", -// "onCommand:C_Cpp.RestartIntelliSenseForFile", -// "onCommand:C_Cpp.ConfigurationEditJSON", -// "onCommand:C_Cpp.ConfigurationEditUI", -// "onCommand:C_Cpp.ConfigurationSelect", -// "onCommand:C_Cpp.ConfigurationProviderSelect", -// "onCommand:C_Cpp.SwitchHeaderSource", -// "onCommand:C_Cpp.EnableErrorSquiggles", -// "onCommand:C_Cpp.DisableErrorSquiggles", -// "onCommand:C_Cpp.ToggleIncludeFallback", -// "onCommand:C_Cpp.ToggleDimInactiveRegions", -// "onCommand:C_Cpp.ResetDatabase", -// "onCommand:C_Cpp.TakeSurvey", -// "onCommand:C_Cpp.LogDiagnostics", -// "onCommand:C_Cpp.RescanWorkspace", -// "onCommand:C_Cpp.VcpkgClipboardInstallSuggested", -// "onCommand:C_Cpp.VcpkgOnlineHelpSuggested", -// "onCommand:C_Cpp.GenerateEditorConfig", -// "onCommand:C_Cpp.GoToNextDirectiveInGroup", -// "onCommand:C_Cpp.GoToPrevDirectiveInGroup", -// "onCommand:C_Cpp.CheckForCompiler", -// "onCommand:C_Cpp.RunCodeAnalysisOnActiveFile", -// "onCommand:C_Cpp.RunCodeAnalysisOnOpenFiles", -// "onCommand:C_Cpp.RunCodeAnalysisOnAllFiles", -// "onCommand:C_Cpp.ClearCodeAnalysisSquiggles", -// "onDebugInitialConfigurations", -// "onDebugResolve:cppdbg", -// "onDebugResolve:cppvsdbg", -// "workspaceContains:/.vscode/c_cpp_properties.json", -// "onFileSystem:cpptools-schema" -// ]; - -// let doTouchExtension: boolean = false; - -// const packageJsonPath: string = util.getExtensionFilePath("package.json"); -// if (packageJsonPath.includes(".vscode-insiders") || -// packageJsonPath.includes(".vscode-server-insiders") || -// packageJsonPath.includes(".vscode-exploration") || -// packageJsonPath.includes(".vscode-server-exploration")) { -// if (packageJson.contributes.configuration.properties['C_Cpp.updateChannel'].default === 'Default') { -// packageJson.contributes.configuration.properties['C_Cpp.updateChannel'].default = 'Insiders'; -// doTouchExtension = true; -// } -// } - -// return util.writeFileText(util.getPackageJsonPath(), util.stringifyPackageJson(packageJson)).then(() => { -// if (doTouchExtension) { -// // This is required to prevent VS Code from using the cached version with the old updateChannel setting. -// util.touchExtensionFolder(); -// } -// }); -// } diff --git a/Extension/src/packageManager.ts b/Extension/src/packageManager.ts deleted file mode 100644 index f646b20184..0000000000 --- a/Extension/src/packageManager.ts +++ /dev/null @@ -1,530 +0,0 @@ -// /* -------------------------------------------------------------------------------------------- -// * Copyright (c) Microsoft Corporation. All Rights Reserved. -// * See 'LICENSE' in the project root for license information. -// * ------------------------------------------------------------------------------------------ */ - -// import * as fs from 'fs'; -// import * as net from 'net'; -// import * as https from 'https'; -// import * as path from 'path'; -// import * as vscode from 'vscode'; -// import * as url from 'url'; -// import * as tmp from 'tmp'; -// import * as yauzl from 'yauzl'; -// import * as mkdirp from 'mkdirp'; - -// import * as util from './common'; -// import { PlatformInformation } from './platform'; -// import * as Telemetry from './telemetry'; -// import { IncomingMessage, ClientRequest } from 'http'; -// import { Logger } from './logger'; -// import * as nls from 'vscode-nls'; -// import { Readable } from 'stream'; -// import * as crypto from 'crypto'; - -// nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })(); -// const localize: nls.LocalizeFunc = nls.loadMessageBundle(); - -// export function isValidPackage(buffer: Buffer, integrity: string): boolean { -// if (integrity && integrity.length > 0) { -// const hash: crypto.Hash = crypto.createHash('sha256'); -// hash.update(buffer); -// const value: string = hash.digest('hex').toUpperCase(); -// return (value === integrity.toUpperCase()); -// } -// // No integrity has been specified -// return false; -// } - -// export interface IPackage { -// // Description of the package -// description: string; - -// // URL of the package -// url: string; - -// // Platforms for which the package should be downloaded -// platforms: string[]; - -// // Architectures for which the package is applicable -// architectures: string[]; - -// // OS Version regex to check if package is applicable -// versionRegex: string; - -// // A flag to indicate if 'versionRegex' should match or not match. -// // Required if versionRegex is used. Default is false. -// matchVersion: boolean; - -// // Binaries in the package that should be executable when deployed -// binaries: string[]; - -// // Internal location to which the package was downloaded -// tmpFile: tmp.FileResult; - -// // sha256 hash of the package -// integrity: string; -// } - -// export class PackageManagerError extends Error { -// public localizedMessageText: string; - -// constructor( -// public message: string, -// public localizedMessage: string, -// public methodName: string, -// public pkg: IPackage | null = null, -// public innerError: Error | null = null, -// public errorCode: string = '') { -// super(message); -// this.localizedMessageText = localizedMessage; -// } -// } - -// export class PackageManagerWebResponseError extends PackageManagerError { -// constructor( -// public socket: net.Socket, -// public message: string, -// public localizedMessage: string, -// public methodName: string, -// public pkg: IPackage | null = null, -// public innerError: Error | null = null, -// public errorCode: string = '') { -// super(message, localizedMessage, methodName, pkg, innerError, errorCode); -// } -// } - -// export class PackageManager { -// private allPackages?: IPackage[]; - -// public constructor( -// private platformInfo: PlatformInformation, -// private outputChannel?: Logger) { -// // Ensure our temp files get cleaned up in case of error -// tmp.setGracefulCleanup(); -// } - -// public async DownloadPackages(progress: vscode.Progress<{ message?: string; increment?: number }>): Promise { -// const packages: IPackage[] = await this.GetPackages(); -// let count: number = 1; -// return util.sequentialResolve(packages, async (pkg): Promise => { -// progress.report({ message: localize("downloading.progress.description", "Downloading {0}", pkg.description), increment: this.GetIncrement(count, packages.length) }); -// count += 1; -// await this.DownloadPackage(pkg); -// }); -// } - -// public async InstallPackages(progress: vscode.Progress<{ message?: string; increment?: number }>): Promise { -// const packages: IPackage[] = await this.GetPackages(); -// let count: number = 1; -// return util.sequentialResolve(packages, async (pkg): Promise => { -// progress.report({ message: localize("installing.progress.description", "Installing {0}", pkg.description), increment: this.GetIncrement(count, packages.length) }); -// count += 1; -// await this.InstallPackage(pkg); -// }); - -// } - -// private GetIncrement(curStep: number, totalSteps: number): number { -// // The first half of the progress bar is assigned to download progress, -// // and the second half of the progress bar is assigned to install progress. -// const maxIncrement: number = 100 / 2; -// const increment: number = Math.floor(maxIncrement / totalSteps); -// return (curStep !== totalSteps) ? increment : maxIncrement - (totalSteps - 1) * increment; -// } - -// public async GetPackages(): Promise { -// const list: IPackage[] = await this.GetPackageList(); -// return list.filter((value, index, array) => ArchitecturesMatch(value, this.platformInfo) && -// PlatformsMatch(value, this.platformInfo) && -// VersionsMatch(value, this.platformInfo) -// ); -// } - -// private GetPackageList(): Promise { -// return new Promise((resolve, reject) => { -// if (!this.allPackages) { -// if (util.packageJson.runtimeDependencies) { -// this.allPackages = util.packageJson.runtimeDependencies; - -// // Convert relative binary paths to absolute -// for (const pkg of this.allPackages) { -// if (pkg.binaries) { -// pkg.binaries = pkg.binaries.map((value) => util.getExtensionFilePath(value)); -// } -// } - -// resolve(this.allPackages); -// } else { -// reject(new PackageManagerError("Package manifest does not exist", localize("package.manager.missing", 'Package manifest does not exist'), 'GetPackageList')); -// } -// } else { -// resolve(this.allPackages); -// } -// }); -// } - -// private async DownloadPackage(pkg: IPackage): Promise { -// this.AppendChannel(localize("downloading.package", "Downloading package '{0}' ", pkg.description)); - -// const tmpResult: tmp.FileResult = await this.CreateTempFile(pkg); -// await this.DownloadPackageWithRetries(pkg, tmpResult); -// } - -// private async CreateTempFile(pkg: IPackage): Promise { -// return new Promise((resolve, reject) => { -// tmp.file({ prefix: "package-" }, (err, path, fd, cleanupCallback) => { -// if (err) { -// return reject(new PackageManagerError("Error from temp.file", localize("error.from", 'Error from {0}', "temp.file"), 'DownloadPackage', pkg, err)); -// } - -// return resolve({ name: path, fd: fd, removeCallback: cleanupCallback }); -// }); -// }); -// } - -// private async DownloadPackageWithRetries(pkg: IPackage, tmpResult: tmp.FileResult): Promise { -// pkg.tmpFile = tmpResult; - -// let success: boolean = false; -// let lastError: Error | null = null; -// let retryCount: number = 0; -// const MAX_RETRIES: number = 10; - -// // Retry the download at most MAX_RETRIES times with 2-32 seconds delay. -// do { -// try { -// await this.DownloadFile(pkg.url, pkg, retryCount); -// success = true; -// } catch (errJS) { -// const error: Error = errJS as Error; -// retryCount += 1; -// lastError = error; -// if (retryCount >= MAX_RETRIES) { -// this.AppendChannel(" " + localize("failed.download.url", "Failed to download {0}", pkg.url)); -// throw error; -// } else { -// this.AppendChannel(" " + localize("failed.retrying", "Failed. Retrying...")); -// continue; -// } -// } -// } while (!success && retryCount < MAX_RETRIES); - -// this.AppendLineChannel(" " + localize("done", "Done!")); -// if (retryCount !== 0) { -// // Log telemetry to see if retrying helps. -// const telemetryProperties: { [key: string]: string } = {}; -// telemetryProperties["success"] = success ? `OnRetry${retryCount}` : 'false'; -// if (lastError instanceof PackageManagerError) { -// const packageError: PackageManagerError = lastError; -// telemetryProperties['error.methodName'] = packageError.methodName; -// telemetryProperties['error.message'] = packageError.message; -// if (packageError.pkg) { -// telemetryProperties['error.packageName'] = packageError.pkg.description; -// telemetryProperties['error.packageUrl'] = packageError.pkg.url; -// } -// if (packageError.errorCode) { -// telemetryProperties['error.errorCode'] = packageError.errorCode; -// } -// } -// Telemetry.logDebuggerEvent("acquisition", telemetryProperties); -// } -// } - -// // reloadCpptoolsJson in main.ts uses ~25% of this function. -// private DownloadFile(urlString: any, pkg: IPackage, delay: number): Promise { -// const parsedUrl: url.Url = url.parse(urlString); -// const proxyStrictSSL: any = vscode.workspace.getConfiguration().get("http.proxyStrictSSL", true); - -// const options: https.RequestOptions = { -// host: parsedUrl.host, -// path: parsedUrl.path, -// agent: util.getHttpsProxyAgent(), -// rejectUnauthorized: proxyStrictSSL -// }; - -// const buffers: Buffer[] = []; -// return new Promise((resolve, reject) => { -// let secondsDelay: number = Math.min(Math.pow(2, delay), 15); -// if (secondsDelay === 1) { -// secondsDelay = 0; -// } -// if (secondsDelay > 4) { -// this.AppendChannel(localize("waiting.seconds", "Waiting {0} seconds...", secondsDelay)); -// } -// setTimeout(() => { -// if (!pkg.tmpFile || pkg.tmpFile.fd === 0) { -// return reject(new PackageManagerError('Temporary Package file unavailable', localize("temp.package.unavailable", 'Temporary Package file unavailable'), 'DownloadFile', pkg)); -// } - -// const handleHttpResponse: (response: IncomingMessage) => void = (response: IncomingMessage) => { -// if (response.statusCode === 301 || response.statusCode === 302) { -// // Redirect - download from new location -// let redirectUrl: string | string[]; -// if (typeof response.headers.location === "string") { -// redirectUrl = response.headers.location; -// } else { -// if (!response.headers.location) { -// return reject(new PackageManagerError('Invalid download location received', localize("invalid.download.location.received", 'Invalid download location received'), 'DownloadFile', pkg)); -// } -// redirectUrl = response.headers.location[0]; -// } -// return resolve(this.DownloadFile(redirectUrl, pkg, 0)); -// } else if (response.statusCode !== 200) { -// if (response.statusCode === undefined || response.statusCode === null) { -// return reject(new PackageManagerError('Invalid response code received', localize("invalid.response.code.received", 'Invalid response code received'), 'DownloadFile', pkg)); -// } -// // Download failed - print error message -// const error: Error = new Error(localize("failed.web.error", "failed (error code '{0}')", response.statusCode)); -// return reject(new PackageManagerWebResponseError(response.socket, 'HTTP/HTTPS Response Error', localize("web.response.error", 'HTTP/HTTPS Response Error'), 'DownloadFile', pkg, error, response.statusCode.toString())); -// } else { -// // Downloading - hook up events -// let contentLength: any = response.headers['content-length']; -// if (typeof response.headers['content-length'] === "string") { -// contentLength = response.headers['content-length']; -// } else { -// if (response.headers['content-length'] === undefined || response.headers['content-length'] === null) { -// return reject(new PackageManagerError('Invalid content length location received', localize("invalid.content.length.received", 'Invalid content length location received'), 'DownloadFile', pkg)); -// } -// contentLength = response.headers['content-length'][0]; -// } -// const packageSize: number = parseInt(contentLength, 10); -// const downloadPercentage: number = 0; -// let dots: number = 0; -// const tmpFile: fs.WriteStream = fs.createWriteStream("", { fd: pkg.tmpFile.fd }); - -// this.AppendChannel(`(${Math.ceil(packageSize / 1024)} KB) `); - -// response.on('data', (data) => { -// buffers.push(data); -// // Update dots after package name in output console -// const newDots: number = Math.ceil(downloadPercentage / 5); -// if (newDots > dots) { -// this.AppendChannel(".".repeat(newDots - dots)); -// dots = newDots; -// } -// }); - -// response.on('end', () => { -// const packageBuffer: Buffer = Buffer.concat(buffers); -// if (isValidPackage(packageBuffer, pkg.integrity)) { -// resolve(); -// } else { -// reject(new PackageManagerError('Invalid content received. Hash is incorrect.', localize("invalid.content.received", 'Invalid content received. Hash is incorrect.'), 'DownloadFile', pkg)); -// } -// }); - -// response.on('error', (errJS) => { -// const error: Error = errJS as Error; -// reject(new PackageManagerWebResponseError(response.socket, 'HTTP/HTTPS Response Error', localize("web.response.error", 'HTTP/HTTPS Response Error'), 'DownloadFile', pkg, error, error.name)); -// }); - -// // Begin piping data from the response to the package file -// response.pipe(tmpFile, { end: false }); -// } -// }; - -// const request: ClientRequest = https.request(options, handleHttpResponse); - -// request.on('error', (error) => -// reject(new PackageManagerError( -// 'HTTP/HTTPS Request error' + (urlString.includes("fwlink") ? ": fwlink" : ""), -// localize("web.request.error", 'HTTP/HTTPS Request error') + (urlString.includes("fwlink") ? ": fwlink" : ""), -// 'DownloadFile', pkg, error, error.message))); - -// // Execute the request -// request.end(); -// }, secondsDelay * 1000); -// }); -// } - -// private InstallPackage(pkg: IPackage): Promise { -// this.AppendLineChannel(localize("installing.package", "Installing package '{0}'", pkg.description)); - -// return new Promise((resolve, reject) => { -// if (!pkg.tmpFile || pkg.tmpFile.fd === 0) { -// return reject(new PackageManagerError('Downloaded file unavailable', localize("downloaded.unavailable", 'Downloaded file unavailable'), 'InstallPackage', pkg)); -// } - -// yauzl.fromFd(pkg.tmpFile.fd, { lazyEntries: true, autoClose: true }, (err, zipfile) => { -// if (err || !zipfile) { -// return reject(new PackageManagerError('Zip file error', localize("zip.file.error", 'Zip file error'), 'InstallPackage', pkg, err)); -// } - -// // setup zip file events - -// // Keep track of any error that occurs, but don't resolve or reject the promise until the file is closed. -// let pendingError: Error | undefined; -// zipfile.on('close', () => { -// if (!pendingError) { -// resolve(); -// } else { -// reject(pendingError); -// } -// }); - -// zipfile.on('error', err => { -// // Don't call reject() a second time. -// // Errors can also arise from readStream and writeStream. -// if (!pendingError) { -// pendingError = new PackageManagerError('Zip file error', localize("zip.file.error", 'Zip file error'), 'InstallPackage', pkg, err, err.code); -// zipfile.close(); -// } -// }); - -// zipfile.on('entry', (entry: yauzl.Entry) => { -// const absoluteEntryPath: string = util.getExtensionFilePath(entry.fileName); - -// if (entry.fileName.endsWith("/")) { -// // Directory - create it -// mkdirp(absoluteEntryPath, { mode: 0o775 }, (err) => { -// if (err) { -// pendingError = new PackageManagerError('Error creating directory', localize("create.directory.error", 'Error creating directory'), 'InstallPackage', pkg, err, err.code); -// zipfile.close(); -// return; -// } - -// zipfile.readEntry(); -// }); -// } else { -// util.checkFileExists(absoluteEntryPath).then((exists: boolean) => { -// if (!exists) { -// // File - extract it -// zipfile.openReadStream(entry, (err, readStream: Readable | undefined) => { -// if (err || !readStream) { -// pendingError = new PackageManagerError('Error reading zip stream', localize("zip.stream.error", 'Error reading zip stream'), 'InstallPackage', pkg, err); -// zipfile.close(); -// return; -// } - -// mkdirp(path.dirname(absoluteEntryPath), { mode: 0o775 }, async (err) => { -// if (err) { -// pendingError = new PackageManagerError('Error creating directory', localize("create.directory.error", 'Error creating directory'), 'InstallPackage', pkg, err, err.code); -// zipfile.close(); -// return; -// } - -// // Create as a .tmp file to avoid partially unzipped files -// // counting as completed files. -// const absoluteEntryTempFile: string = absoluteEntryPath + ".tmp"; -// if (await util.checkFileExists(absoluteEntryTempFile)) { -// try { -// await util.unlinkAsync(absoluteEntryTempFile); -// } catch (errJS) { -// const err: Error = errJS as Error; -// pendingError = new PackageManagerError(`Error unlinking file ${absoluteEntryTempFile}`, localize("unlink.error", "Error unlinking file {0}", absoluteEntryTempFile), 'InstallPackage', pkg, err); -// zipfile.close(); -// return; -// } -// } - -// // Make sure executable files have correct permissions when extracted -// const fileMode: number = (this.platformInfo.platform !== "win32" && pkg.binaries && pkg.binaries.indexOf(absoluteEntryPath) !== -1) ? 0o755 : 0o664; -// const writeStream: fs.WriteStream = fs.createWriteStream(absoluteEntryTempFile, { mode: fileMode }); - -// writeStream.on('close', async () => { -// // Remove .tmp extension from the file, if there was no error. -// // Otherwise, delete it. -// // Don't move on to the next entry, if we've already called reject(), in -// // which case zipfile.close() will already have been called. -// if (!pendingError) { -// try { -// await util.renameAsync(absoluteEntryTempFile, absoluteEntryPath); -// } catch (errJS) { -// const err: Error = errJS as Error; -// pendingError = new PackageManagerError(`Error renaming file ${absoluteEntryTempFile}`, localize("rename.error", "Error renaming file {0}", absoluteEntryTempFile), 'InstallPackage', pkg, err); -// zipfile.close(); -// return; -// } -// // Wait until output is done writing before reading the next zip entry. -// // Otherwise, it's possible to try to launch the .exe before it is done being created. -// zipfile.readEntry(); -// } else { -// try { -// await util.unlinkAsync(absoluteEntryTempFile); -// } catch (err) { -// // Ignore failure to delete temp file. We already have an error to return. -// } -// } -// }); - -// readStream.on('error', (err) => { -// // Don't call reject() a second time. -// if (!pendingError) { -// pendingError = new PackageManagerError('Error in readStream', localize("read.stream.error", 'Error in read stream'), 'InstallPackage', pkg, err); -// zipfile.close(); -// } -// }); - -// writeStream.on('error', (err) => { -// // Don't call reject() a second time. -// if (!pendingError) { -// pendingError = new PackageManagerError('Error in writeStream', localize("write.stream.error", 'Error in write stream'), 'InstallPackage', pkg, err); -// zipfile.close(); -// } -// }); - -// readStream.pipe(writeStream); -// }); -// }); -// } else { -// // Skip the message for text files, because there is a duplicate text file unzipped. -// if (path.extname(absoluteEntryPath) !== ".txt") { -// this.AppendLineChannel(localize("file.already.exists", "Warning: File '{0}' already exists and was not updated.", absoluteEntryPath)); -// } -// zipfile.readEntry(); -// } -// }); -// } -// }); - -// zipfile.readEntry(); -// }); -// }).then(() => { -// // Clean up temp file -// pkg.tmpFile.removeCallback(); -// }); -// } - -// private AppendChannel(text: string): void { -// if (this.outputChannel) { -// this.outputChannel.append(text); -// } -// } - -// private AppendLineChannel(text: string): void { -// if (this.outputChannel) { -// this.outputChannel.appendLine(text); -// } -// } -// } - -// export function VersionsMatch(pkg: IPackage, info: PlatformInformation): boolean { -// if (pkg.versionRegex) { -// // If we have a versionRegex but did not get a platformVersion -// if (!info.version) { -// // If we are expecting to match the versionRegex, return false since there was no version found. -// // -// // If we are expecting to not match the versionRegex, return true since we are expecting to -// // not match the version string, the only match would be if versionRegex was not set. -// return !pkg.matchVersion; -// } -// const regex: RegExp = new RegExp(pkg.versionRegex); - -// return (pkg.matchVersion ? -// regex.test(info.version) : -// !regex.test(info.version) -// ); -// } - -// // No versionRegex provided. -// return true; -// } - -// export function ArchitecturesMatch(value: IPackage, info: PlatformInformation): boolean { -// return !value.architectures || (value.architectures.indexOf(info.architecture) !== -1); -// } - -// export function PlatformsMatch(value: IPackage, info: PlatformInformation): boolean { -// return !value.platforms || value.platforms.indexOf(info.platform) !== -1; -// } From 091d75e7c4ad101488ee485dd389273cd449c4a5 Mon Sep 17 00:00:00 2001 From: Colen Garoutte-Carson Date: Tue, 7 Dec 2021 16:57:04 -0800 Subject: [PATCH 03/15] Remove hash generation for runtime dependencies --- .github/workflows/ci_linux.yml | 4 -- .github/workflows/ci_mac.yml | 4 -- .github/workflows/ci_windows.yml | 4 -- Extension/gulpfile.js | 103 ------------------------------- Extension/package.json | 1 - 5 files changed, 116 deletions(-) diff --git a/.github/workflows/ci_linux.yml b/.github/workflows/ci_linux.yml index d307e13a1a..af19fddb5c 100644 --- a/.github/workflows/ci_linux.yml +++ b/.github/workflows/ci_linux.yml @@ -22,10 +22,6 @@ jobs: run: yarn install working-directory: Extension - - name: Generate hashes for runtime dependency packages - run: yarn run generatePackageHashes - working-directory: Extension - - name: Compile Sources run: yarn run compile working-directory: Extension diff --git a/.github/workflows/ci_mac.yml b/.github/workflows/ci_mac.yml index a80f659a8a..06aab572ef 100644 --- a/.github/workflows/ci_mac.yml +++ b/.github/workflows/ci_mac.yml @@ -22,10 +22,6 @@ jobs: run: yarn install --network-timeout 100000 working-directory: Extension - - name: Generate hashes for runtime dependency packages - run: yarn run generatePackageHashes - working-directory: Extension - - name: Compile Sources run: yarn run compile working-directory: Extension diff --git a/.github/workflows/ci_windows.yml b/.github/workflows/ci_windows.yml index 61da517bd1..687c78a9ec 100644 --- a/.github/workflows/ci_windows.yml +++ b/.github/workflows/ci_windows.yml @@ -22,10 +22,6 @@ jobs: run: yarn install working-directory: Extension - - name: Generate hashes for runtime dependency packages - run: yarn run generatePackageHashes - working-directory: Extension - - name: Compile Sources run: yarn run compile working-directory: Extension diff --git a/Extension/gulpfile.js b/Extension/gulpfile.js index 8f35726215..78372abf61 100644 --- a/Extension/gulpfile.js +++ b/Extension/gulpfile.js @@ -301,109 +301,6 @@ gulp.task("translations-import", (done) => { })); }); -// **************************** -// Command: generate-package-hashes -// Generates a hash for each dependency package -// **************************** - -async function DownloadFile(urlString) { - const buffers = []; - return new Promise((resolve, reject) => { - const req = https.request(urlString, (response) => { - if (response.statusCode === 301 || response.statusCode === 302) { - // Redirect - download from new location - let redirectUrl; - if (typeof response.headers.location === "string") { - redirectUrl = response.headers.location; - } else { - if (!response.headers.location) { - console.log(`Invalid download location received`); - return reject(); - } - redirectUrl = response.headers.location[0]; - } - console.log(`Using redirectUrl: '${redirectUrl}'`); - return resolve(DownloadFile(redirectUrl)); - } else if (response.statusCode !== 200) { - if (response.statusCode === undefined || response.statusCode === null) { - console.log("unknown error code."); - return reject(); - } - console.log(`failed with error code: '${response.statusCode}'`); - return reject(); - } - - response.on('data', (data) => { - buffers.push(data); - }); - - response.on('end', () => { - if (buffers.length > 0) { - return resolve(Buffer.concat(buffers)); - } else { - return reject(); - } - }); - - response.on('error', err => { - console.log(`problem with request: '${err.message}'`); - return reject(); - }); - }); - - req.on('error', err => { - console.log(`problem with request: '${err.message}'`); - return reject(); - }); - - // Execute the request - req.end(); - }); - -} - -async function generatePackageHashes(packageJson) { - const downloadAndGetHash = async (url) => { - console.log(url); - try { - const buf = await DownloadFile(url); - if (buf) { - const hash = crypto.createHash('sha256'); - hash.update(buf); - const value = hash.digest('hex').toUpperCase(); - return value; - } - return undefined; - } catch (err) { - return undefined; - } - }; - - for (let dependency of packageJson.runtimeDependencies) { - console.log(`-------- Downloading package: '${dependency.description}' --------`); - const hash = await downloadAndGetHash(dependency.url); - if (hash) { - dependency.integrity = hash; - console.log(`integrity: '${hash}'`); - } else { - console.log(`No hash generated for package '${dependency.description}`); - } - console.log(`\n`); - } - - let content = JSON.stringify(packageJson, null, 2); - return content; -} - -gulp.task('generate-package-hashes', async (done) => { - const packageJsonPath = './package.json'; - const packageJson = JSON.parse(fs.readFileSync(packageJsonPath).toString()); - const content = await generatePackageHashes(packageJson); - fs.writeFileSync(packageJsonPath, content); - done(); -}); - - // **************************** // Command: translations-generate // The following is used to import an i18n directory structure and generate files used at runtime. diff --git a/Extension/package.json b/Extension/package.json index 39bb78b125..cf9cebda3e 100644 --- a/Extension/package.json +++ b/Extension/package.json @@ -4336,7 +4336,6 @@ "translations-import": "node ./tools/prepublish.js && gulp translations-import", "prepublishjs": "node ./tools/prepublish.js", "pretest": "tsc -p test.tsconfig.json", - "generatePackageHashes": "gulp generate-package-hashes", "pr-check": "gulp pr-check", "lint": "gulp lint", "unitTests": "tsc -p test.tsconfig.json && node ./out/test/unitTests/runTest.js", From a53313256e6506fb7ff7fd7e204351c5c88a1364 Mon Sep 17 00:00:00 2001 From: Colen Garoutte-Carson Date: Tue, 7 Dec 2021 17:06:06 -0800 Subject: [PATCH 04/15] Remove pr-check --- .github/workflows/ci_linux.yml | 4 ---- .github/workflows/ci_mac.yml | 4 ---- .github/workflows/ci_windows.yml | 4 ---- Extension/gulpfile.js | 11 ----------- Extension/package.json | 1 - 5 files changed, 24 deletions(-) diff --git a/.github/workflows/ci_linux.yml b/.github/workflows/ci_linux.yml index af19fddb5c..0192ef79c2 100644 --- a/.github/workflows/ci_linux.yml +++ b/.github/workflows/ci_linux.yml @@ -26,10 +26,6 @@ jobs: run: yarn run compile working-directory: Extension - - name: Validate Extension/package.json - run: yarn run pr-check - working-directory: Extension - - name: Run Linter run: yarn run lint working-directory: Extension diff --git a/.github/workflows/ci_mac.yml b/.github/workflows/ci_mac.yml index 06aab572ef..e614d02d90 100644 --- a/.github/workflows/ci_mac.yml +++ b/.github/workflows/ci_mac.yml @@ -26,10 +26,6 @@ jobs: run: yarn run compile working-directory: Extension - - name: Validate Extension/package.json - run: yarn run pr-check - working-directory: Extension - - name: Run Linter run: yarn run lint working-directory: Extension diff --git a/.github/workflows/ci_windows.yml b/.github/workflows/ci_windows.yml index 687c78a9ec..3c16c93cac 100644 --- a/.github/workflows/ci_windows.yml +++ b/.github/workflows/ci_windows.yml @@ -26,10 +26,6 @@ jobs: run: yarn run compile working-directory: Extension - - name: Validate Extension/package.json - run: yarn run pr-check - working-directory: Extension - - name: Run Linter run: yarn run lint working-directory: Extension diff --git a/Extension/gulpfile.js b/Extension/gulpfile.js index 78372abf61..94bf3d044e 100644 --- a/Extension/gulpfile.js +++ b/Extension/gulpfile.js @@ -71,17 +71,6 @@ gulp.task('lint', function () { .pipe(eslint.failAfterError()); }); -gulp.task('pr-check', (done) => { - const packageJson = JSON.parse(fs.readFileSync('./package.json').toString()); - if (packageJson.activationEvents.length !== 1 && packageJson.activationEvents[0] !== '*') { - console.log('Please make sure to not check in package.json that has been rewritten by the extension activation. If you intended to have changes in package.json, please only check-in your changes. If you did not, please run `git checkout -- package.json`.'); - done(); - process.exit(1); - } - - done(); -}); - // **************************** // Command: translations-export diff --git a/Extension/package.json b/Extension/package.json index cf9cebda3e..536d084238 100644 --- a/Extension/package.json +++ b/Extension/package.json @@ -4336,7 +4336,6 @@ "translations-import": "node ./tools/prepublish.js && gulp translations-import", "prepublishjs": "node ./tools/prepublish.js", "pretest": "tsc -p test.tsconfig.json", - "pr-check": "gulp pr-check", "lint": "gulp lint", "unitTests": "tsc -p test.tsconfig.json && node ./out/test/unitTests/runTest.js", "integrationTests": "tsc -p test.tsconfig.json && node ./out/test/integrationTests/languageServer/runTest.js", From 9c2e0b14c7a1a6f011a6958a604cabdb21b76f12 Mon Sep 17 00:00:00 2001 From: Colen Garoutte-Carson Date: Tue, 7 Dec 2021 17:21:04 -0800 Subject: [PATCH 05/15] Add temporary logging to investigate a test failure (that doesn't repro locally) --- Extension/src/LanguageServer/client.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Extension/src/LanguageServer/client.ts b/Extension/src/LanguageServer/client.ts index ee24098628..bd5738535f 100644 --- a/Extension/src/LanguageServer/client.ts +++ b/Extension/src/LanguageServer/client.ts @@ -1045,6 +1045,9 @@ export class DefaultClient implements Client { } } catch (err) { this.isSupported = false; // Running on an OS we don't support yet. + console.log("---------------------"); + console.log(String(err)); + console.log("---------------------"); if (!failureMessageShown) { failureMessageShown = true; vscode.window.showErrorMessage(localize("unable.to.start", "Unable to start the C/C++ language server. IntelliSense features will be disabled. Error: {0}", String(err))); @@ -1054,6 +1057,9 @@ export class DefaultClient implements Client { } catch (errJS) { const err: NodeJS.ErrnoException = errJS as NodeJS.ErrnoException; this.isSupported = false; // Running on an OS we don't support yet. + console.log("---------------------"); + console.log(String(err)); + console.log("---------------------"); if (!failureMessageShown) { failureMessageShown = true; let additionalInfo: string; From 73dbf16d23f745c6688d29f099201a541121fa5a Mon Sep 17 00:00:00 2001 From: Colen Garoutte-Carson Date: Thu, 9 Dec 2021 12:10:38 -0800 Subject: [PATCH 06/15] Remove updateChannel setting and insider VSIX install logic --- Extension/package.json | 10 - Extension/src/LanguageServer/extension.ts | 323 +-------------------- Extension/src/LanguageServer/settings.ts | 1 - Extension/src/githubAPI.ts | 335 ---------------------- Extension/src/packageVersion.ts | 4 - 5 files changed, 1 insertion(+), 672 deletions(-) delete mode 100644 Extension/src/githubAPI.ts diff --git a/Extension/package.json b/Extension/package.json index 536d084238..5105b64f3f 100644 --- a/Extension/package.json +++ b/Extension/package.json @@ -2472,16 +2472,6 @@ "markdownDescription": "%c_cpp.configuration.default.enableConfigurationSquiggles.markdownDescription%", "scope": "resource" }, - "C_Cpp.updateChannel": { - "type": "string", - "enum": [ - "Default", - "Insiders" - ], - "default": "Default", - "markdownDescription": "%c_cpp.configuration.updateChannel.markdownDescription%", - "scope": "application" - }, "C_Cpp.experimentalFeatures": { "type": "string", "enum": [ diff --git a/Extension/src/LanguageServer/extension.ts b/Extension/src/LanguageServer/extension.ts index 068756c2fb..be995ea4bd 100644 --- a/Extension/src/LanguageServer/extension.ts +++ b/Extension/src/LanguageServer/extension.ts @@ -18,18 +18,12 @@ import { CppSettings, OtherSettings } from './settings'; import { PersistentState } from './persistentState'; import { getLanguageConfig } from './languageConfig'; import { getCustomConfigProviders } from './customProviders'; -import { PlatformInformation } from '../platform'; import { Range } from 'vscode-languageclient'; -import { ChildProcess, spawn } from 'child_process'; -import { getTargetBuildInfo, BuildInfo } from '../githubAPI'; -import { PackageVersion } from '../packageVersion'; import * as rd from 'readline'; import * as yauzl from 'yauzl'; -import { Readable, Writable } from 'stream'; +import { Readable } from 'stream'; import * as nls from 'vscode-nls'; import { CppBuildTaskProvider } from './cppBuildTaskProvider'; -import * as which from 'which'; -import { IExperimentationService } from 'tas-client'; nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })(); const localize: nls.LocalizeFunc = nls.loadMessageBundle(); @@ -42,11 +36,6 @@ let ui: UI; const disposables: vscode.Disposable[] = []; let languageConfigurations: vscode.Disposable[] = []; let intervalTimer: NodeJS.Timer; -let insiderUpdateEnabled: boolean = false; -let insiderUpdateTimer: NodeJS.Timer; -const insiderUpdateTimerInterval: number = 1000 * 60 * 60; -let buildInfoCache: BuildInfo | undefined; -const cppInstallVsixStr: string = 'C/C++: Install vsix -- '; let taskProvider: vscode.Disposable; let codeActionProvider: vscode.Disposable; export const intelliSenseDisabledError: string = "Do not activate the extension when IntelliSense is disabled."; @@ -280,36 +269,8 @@ export async function activate(): Promise { reportMacCrashes(); - const settings: CppSettings = new CppSettings(); - vcpkgDbPromise = initVcpkgDatabase(); - PlatformInformation.GetPlatformInformation().then(async info => { - // Skip Insiders processing for 32-bit Linux. - if (info.platform !== "linux" || info.architecture === "x64" || info.architecture === "arm" || info.architecture === "arm64") { - // Skip Insiders processing for unsupported VS Code versions. - const experimentationService: IExperimentationService | undefined = await telemetry.getExperimentationService(); - // If we can't get to the experimentation service, don't suggest Insiders. - if (experimentationService !== undefined) { - const allowInsiders: boolean | undefined = await experimentationService.getTreatmentVariableAsync("vscode", "allowInsiders"); - // If we can't get the minimum supported VS Code version for Insiders, don't suggest Insiders. - if (allowInsiders) { - insiderUpdateEnabled = true; - if (settings.updateChannel === 'Default') { - const userVersion: PackageVersion = new PackageVersion(util.packageJson.version); - if (userVersion.suffix === "insiders") { - checkAndApplyUpdate(settings.updateChannel, false); - } else { - suggestInsidersChannel(); - } - } else if (settings.updateChannel === 'Insiders') { - insiderUpdateTimer = global.setInterval(checkAndApplyUpdateOnTimer, insiderUpdateTimerInterval); - checkAndApplyUpdate(settings.updateChannel, false); - } - } - } - } - }); clients.ActiveClient.notifyWhenLanguageClientReady(() => { intervalTimer = global.setInterval(onInterval, 2500); }); @@ -329,25 +290,11 @@ export function updateLanguageConfigurations(): void { */ function onDidChangeSettings(event: vscode.ConfigurationChangeEvent): void { const activeClient: Client = clients.ActiveClient; - const changedActiveClientSettings: { [key: string]: string } = activeClient.onDidChangeSettings(event, true); clients.forEach(client => { if (client !== activeClient) { client.onDidChangeSettings(event, false); } }); - - if (insiderUpdateEnabled) { - const newUpdateChannel: string = changedActiveClientSettings['updateChannel']; - if (newUpdateChannel) { - if (newUpdateChannel === 'Default') { - clearInterval(insiderUpdateTimer); - } else if (newUpdateChannel === 'Insiders') { - insiderUpdateTimer = global.setInterval(checkAndApplyUpdateOnTimer, insiderUpdateTimerInterval); - } - - checkAndApplyUpdate(newUpdateChannel, true); - } - } } export function onDidChangeActiveTextEditor(editor?: vscode.TextEditor): void { @@ -443,273 +390,6 @@ function onInterval(): void { clients.ActiveClient.onInterval(); } -/** - * Install a VSIX package. This helper function will exist until VSCode offers a command to do so. - * @param updateChannel The user's updateChannel setting. - */ -async function installVsix(vsixLocation: string): Promise { - const userVersion: PackageVersion = new PackageVersion(vscode.version); - - // 1.33.0 introduces workbench.extensions.installExtension. 1.32.3 was immediately prior. - const lastVersionWithoutInstallExtensionCommand: PackageVersion = new PackageVersion('1.32.3'); - if (userVersion.isVsCodeVersionGreaterThan(lastVersionWithoutInstallExtensionCommand)) { - return vscode.commands.executeCommand('workbench.extensions.installExtension', vscode.Uri.file(vsixLocation)); - } - - // Get the path to the VSCode command -- replace logic later when VSCode allows calling of - // workbench.extensions.action.installVSIX from TypeScript w/o instead popping up a file dialog - return PlatformInformation.GetPlatformInformation().then((platformInfo) => { - const getVsCodeScriptPath = (platformInfo: any): string => { - if (platformInfo.platform === 'win32') { - const vsCodeBinName: string = path.basename(process.execPath); - let cmdFile: string; // Windows VS Code Insiders/Exploration breaks VS Code naming conventions - if (vsCodeBinName === 'Code - Insiders.exe') { - cmdFile = 'code-insiders.cmd'; - } else if (vsCodeBinName === 'Code - Exploration.exe') { - cmdFile = 'code-exploration.cmd'; - } else { - cmdFile = 'code.cmd'; - } - const vsCodeExeDir: string = path.dirname(process.execPath); - return path.join(vsCodeExeDir, 'bin', cmdFile); - } else if (platformInfo.platform === 'darwin') { - return path.join(process.execPath, '..', '..', '..', '..', '..', - 'Resources', 'app', 'bin', 'code'); - } else { - const vsCodeBinName: string = path.basename(process.execPath); - return which.sync(vsCodeBinName); - } - }; - let vsCodeScriptPath: string; - try { - vsCodeScriptPath = getVsCodeScriptPath(platformInfo); - } catch (err) { - return Promise.reject(new Error('Failed to find VS Code script')); - } - - // 1.28.0 changes the CLI for making installations. 1.27.2 was immediately prior. - const oldVersion: PackageVersion = new PackageVersion('1.27.2'); - if (userVersion.isVsCodeVersionGreaterThan(oldVersion)) { - return new Promise((resolve, reject) => { - let process: ChildProcess; - try { - process = spawn(vsCodeScriptPath, ['--install-extension', vsixLocation, '--force']); - - // Timeout the process if no response is sent back. Ensures this Promise resolves/rejects - const timer: NodeJS.Timer = global.setTimeout(() => { - process.kill(); - reject(new Error('Failed to receive response from VS Code script process for installation within 30s.')); - }, 30000); - - process.on('exit', (code: number) => { - clearInterval(timer); - if (code !== 0) { - reject(new Error(`VS Code script exited with error code ${code}`)); - } else { - resolve(); - } - }); - if (process.pid === undefined) { - throw new Error(); - } - } catch (error) { - reject(new Error('Failed to launch VS Code script process for installation')); - return; - } - }); - } - - return new Promise((resolve, reject) => { - let process: ChildProcess; - try { - process = spawn(vsCodeScriptPath, ['--install-extension', vsixLocation]); - if (process.pid === undefined) { - throw new Error(); - } - } catch (error) { - reject(new Error('Failed to launch VS Code script process for installation')); - return; - } - - // Timeout the process if no response is sent back. Ensures this Promise resolves/rejects - const timer: NodeJS.Timer = global.setTimeout(() => { - process.kill(); - reject(new Error('Failed to receive response from VS Code script process for installation within 30s.')); - }, 30000); - - // If downgrading, the VS Code CLI will prompt whether the user is sure they would like to downgrade. - // Respond to this by writing 0 to stdin (the option to override and install the VSIX package) - let sentOverride: boolean = false; - const stdout: Readable | null = process.stdout; - if (!stdout) { - reject(new Error("Failed to communicate with VS Code script process for installation")); - return; - } - stdout.on('data', () => { - if (sentOverride) { - return; - } - const stdin: Writable | null = process.stdin; - if (!stdin) { - reject(new Error("Failed to communicate with VS Code script process for installation")); - return; - } - stdin.write('0\n'); - sentOverride = true; - clearInterval(timer); - resolve(); - }); - }); - }); -} - -async function suggestInsidersChannel(): Promise { - if (util.isCodespaces()) { - // Do not prompt users of Codespaces to join Insiders. - return; - } - - const suggestInsiders: PersistentState = new PersistentState("CPP.suggestInsiders", true); - - if (!suggestInsiders.Value) { - return; - } - - const suggestInsidersCount: PersistentState = new PersistentState("CPP.suggestInsidersCount", 0); - - if (suggestInsidersCount.Value < 10) { - suggestInsidersCount.Value = suggestInsidersCount.Value + 1; - return; - } - - let buildInfo: BuildInfo | undefined; - try { - buildInfo = await getTargetBuildInfo("Insiders", false); - } catch (errJS) { - const error: Error = errJS as Error; - console.log(`${cppInstallVsixStr}${error.message}`); - if (error.message.indexOf('/') !== -1 || error.message.indexOf('\\') !== -1) { - error.message = "Potential PII hidden"; - } - telemetry.logLanguageServerEvent('suggestInsiders', { 'error': error.message, 'success': 'false' }); - } - if (!buildInfo) { - return; // No need to update. - } - const message: string = localize('insiders.available', "Insiders version {0} is available. Would you like to switch to the Insiders channel and install this update?", buildInfo.name); - const yes: string = localize("yes.button", "Yes"); - const askLater: string = localize("ask.me.later.button", "Ask Me Later"); - const dontShowAgain: string = localize("dont.show.again.button", "Don't Show Again"); - vscode.window.showInformationMessage(message, yes, askLater, dontShowAgain).then((selection) => { - switch (selection) { - case yes: - // Cache buildInfo. - buildInfoCache = buildInfo; - // It will call onDidChangeSettings. - vscode.workspace.getConfiguration("C_Cpp").update("updateChannel", "Insiders", vscode.ConfigurationTarget.Global); - break; - case dontShowAgain: - suggestInsiders.Value = false; - break; - case askLater: - break; - default: - break; - } - }); - -} - -async function applyUpdate(buildInfo: BuildInfo): Promise { - let tempVSIX: any; - try { - tempVSIX = await util.createTempFileWithPostfix('.vsix'); - - // Try to download VSIX - const config: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration(); - const originalProxySupport: string | undefined = config.inspect('http.proxySupport')?.globalValue; - while (true) { // Might need to try again with a different http.proxySupport setting. - try { - await util.downloadFileToDestination(buildInfo.downloadUrl, tempVSIX.name); - } catch { - // Try again with the proxySupport to "off". - if (originalProxySupport !== config.inspect('http.proxySupport')?.globalValue) { - config.update('http.proxySupport', originalProxySupport, true); // Reset the http.proxySupport. - throw new Error('Failed to download VSIX package with proxySupport off'); // Changing the proxySupport didn't help. - } - if (config.get('http.proxySupport') !== "off" && originalProxySupport !== "off") { - config.update('http.proxySupport', "off", true); - continue; - } - throw new Error('Failed to download VSIX package'); - } - if (originalProxySupport !== config.inspect('http.proxySupport')?.globalValue) { - config.update('http.proxySupport', originalProxySupport, true); // Reset the http.proxySupport. - telemetry.logLanguageServerEvent('installVsix', { 'error': "Success with proxySupport off", 'success': 'true' }); - } - break; - } - - // Install VSIX - try { - await installVsix(tempVSIX.name); - } catch (error) { - throw new Error('Failed to install VSIX package'); - } - - // Installation successful - clearInterval(insiderUpdateTimer); - const message: string = localize("extension.updated", - "The C/C++ Extension has been updated to version {0}. Please reload the window for the changes to take effect.", - buildInfo.name); - util.promptReloadWindow(message); - telemetry.logLanguageServerEvent('installVsix', { 'success': 'true' }); - - } catch (errJS) { - const error: Error = errJS as Error; - console.error(`${cppInstallVsixStr}${error.message}`); - if (error.message.indexOf('/') !== -1 || error.message.indexOf('\\') !== -1) { - error.message = "Potential PII hidden"; - } - telemetry.logLanguageServerEvent('installVsix', { 'error': error.message, 'success': 'false' }); - } - - // Delete temp VSIX file - if (tempVSIX) { - tempVSIX.removeCallback(); - } -} - -async function checkAndApplyUpdateOnTimer(): Promise { - return checkAndApplyUpdate('Insiders', false); -} - -/** - * Query package.json and the GitHub API to determine whether the user should update, if so then install the update. - * The update can be an upgrade or downgrade depending on the the updateChannel setting. - * @param updateChannel The user's updateChannel setting. - * @param isFromSettingsChange True if the invocation is the result of a settings change. - */ -async function checkAndApplyUpdate(updateChannel: string, isFromSettingsChange: boolean): Promise { - // If we have buildInfo cache, we should use it. - let buildInfo: BuildInfo | undefined = buildInfoCache; - // clear buildInfo cache. - buildInfoCache = undefined; - - if (!buildInfo) { - try { - buildInfo = await getTargetBuildInfo(updateChannel, isFromSettingsChange); - } catch (errJS) { - const error: Error = errJS as Error; - telemetry.logLanguageServerEvent('installVsix', { 'error': error.message, 'success': 'false' }); - } - } - if (!buildInfo) { - return; // No need to update. - } - await applyUpdate(buildInfo); -} - /** * registered commands */ @@ -1244,7 +924,6 @@ export function deactivate(): Thenable { console.log("deactivating extension"); telemetry.logLanguageServerEvent("LanguageServerShutdown"); clearInterval(intervalTimer); - clearInterval(insiderUpdateTimer); disposables.forEach(d => d.dispose()); languageConfigurations.forEach(d => d.dispose()); ui.dispose(); diff --git a/Extension/src/LanguageServer/settings.ts b/Extension/src/LanguageServer/settings.ts index ec3f5eb6b1..e2029cba03 100644 --- a/Extension/src/LanguageServer/settings.ts +++ b/Extension/src/LanguageServer/settings.ts @@ -211,7 +211,6 @@ export class CppSettings extends Settings { public get commentContinuationPatterns(): (string | CommentPattern)[] | undefined { return super.Section.get<(string | CommentPattern)[]>("commentContinuationPatterns"); } public get configurationWarnings(): string | undefined { return super.Section.get("configurationWarnings"); } public get preferredPathSeparator(): string | undefined { return super.Section.get("preferredPathSeparator"); } - public get updateChannel(): string | undefined { return super.Section.get("updateChannel"); } public get vcpkgEnabled(): boolean | undefined { return super.Section.get("vcpkg.enabled"); } public get addNodeAddonIncludePaths(): boolean | undefined { return super.Section.get("addNodeAddonIncludePaths"); } public get renameRequiresIdentifier(): boolean | undefined { return super.Section.get("renameRequiresIdentifier"); } diff --git a/Extension/src/githubAPI.ts b/Extension/src/githubAPI.ts deleted file mode 100644 index ca915e6b42..0000000000 --- a/Extension/src/githubAPI.ts +++ /dev/null @@ -1,335 +0,0 @@ -/* -------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All Rights Reserved. - * See 'LICENSE' in the project root for license information. - * ------------------------------------------------------------------------------------------ */ -'use strict'; - -import { PackageVersion } from './packageVersion'; -import * as util from './common'; -import { PlatformInformation } from './platform'; -import { OutgoingHttpHeaders } from 'http'; -import * as vscode from 'vscode'; -import * as telemetry from './telemetry'; - -const testingInsidersVsixInstall: boolean = false; // Change this to true to enable testing of the Insiders vsix installation. -export const releaseDownloadUrl: string = "https://github.com/microsoft/vscode-cpptools/releases"; -/** - * The object representation of a Build Asset. Each Asset corresponds to information about a release file on GitHub. - */ -export interface Asset { - name: string; - browser_download_url: string; -} - -/** - * The object representation of a release in the GitHub API's release JSON. - * Named Build so as to reduce confusion between a "Release" release and "Insiders" release. - */ -export interface Build { - name: string; - assets: Asset[]; -} - -/** -* Search each Asset by name to retrieve the download URL for a VSIX package -* @param vsixName The name of the VSIX to search for -* @return The download URL of the VSIX -*/ -function getVsixDownloadUrl(build: Build, vsixName: string): string { - const asset: Asset | undefined = build.assets.find(asset => asset.name === vsixName); - const downloadUrl: string | null = (asset) ? asset.browser_download_url : null; - if (!downloadUrl) { - throw new Error(`Failed to find VSIX: ${vsixName} in build: ${build.name}`); - } - return downloadUrl; -} - -/** - * Determine whether an object is of type Asset. - * @param input Incoming object. - * @return Whether input is of type Asset. - */ -function isAsset(input: any): input is Asset { - return input && input.name && typeof(input.name) === "string" && - input.browser_download_url && typeof(input.browser_download_url) === "string"; -} - -/** - * Determine whether an object is of type Build. - * @param input Incoming object. - * @return Whether input is of type Build. - */ -function isBuild(input: any): input is Build { - return input && input.name && typeof (input.name) === "string" && isArrayOfAssets(input.assets); -} - -/** - * Determine whether an object is of type Build, and it has 3 or more assets (i.e valid build). - * Note that earlier releases of the extension do not have 3 or greater Assets - * (Mac, Win, Linux). Only call this on more recent Builds. - * @param input Incoming object. - * @return Whether input is a valid build. - */ -function isValidBuild(input: any): input is Build { - return isBuild(input) && input.assets.length >= 3; -} - -/** - * Determine whether an object is of type Asset[]. - * @param input Incoming object. - * @return Whether input is of type Asset[]. - */ -function isArrayOfAssets(input: any): input is Asset[] { - return input instanceof Array && input.every(isAsset); -} - -/** - * Return the most recent released builds. - * @param input Incoming object. - * @return An array of type Build[]. - */ -function getArrayOfBuilds(input: any): Build[] { - const builds: Build[] = []; - if (!input || !(input instanceof Array) || input.length === 0) { - return builds; - } - // Only return the the most recent release and insider builds. - for (let i: number = 0; i < input.length; i++) { - if (isBuild(input[i])) { - builds.push(input[i]); - // the latest "valid" released build - if (input[i].name.indexOf('-') === -1 && isValidBuild(input[i])) { - break; - } - } - } - return builds; -} - -/** - * Match the user's platform information to the VSIX name relevant to them. - * @param info Information about the user's operating system. - * @return VSIX filename for the extension's releases matched to the user's platform. - */ -export function vsixNameForPlatform(info: PlatformInformation): string { - const vsixName: string | undefined = function(platformInfo): string | undefined { - switch (platformInfo.platform) { - case 'win32': - switch (platformInfo.architecture) { - case 'x64': return 'cpptools-win32.vsix'; // TODO: Change to cpptools-win64? - case 'x86': return 'cpptools-win32.vsix'; - case 'arm64': return 'cpptools-win-arm64.vsix'; - default: throw new Error(`Unexpected Windows architecture: ${platformInfo.architecture}`); - } - case 'darwin': - switch (platformInfo.architecture) { - case 'x64': return 'cpptools-osx.vsix'; - case 'arm64': return 'cpptools-osx-arm64.vsix'; - default: throw new Error(`Unexpected macOS architecture: ${platformInfo.architecture}`); - } - default: { - switch (platformInfo.architecture) { - case 'x64': return 'cpptools-linux.vsix'; - case 'arm': return 'cpptools-linux-armhf.vsix'; - case 'arm64': return 'cpptools-linux-aarch64.vsix'; - default: throw new Error(`Unexpected Linux architecture: ${platformInfo.architecture}`); - } - } - } - }(info); - if (!vsixName) { - throw new Error(`Failed to match VSIX name for: ${info.platform}: ${info.architecture}`); - } - return vsixName; -} - -/** - * Interface for return value of getTargetBuildInfo containing the download URL and version of a Build. - */ -export interface BuildInfo { - downloadUrl: string; - name: string; -} - -/** - * Use the GitHub API to retrieve the download URL of the extension version the user should update to, if any. - * @param updateChannel The user's updateChannel setting. - * @param isFromSettingsChange True if the invocation is the result of a settings change. - * @return Download URL for the extension VSIX package that the user should install. If the user - * does not need to update, resolves to undefined. - */ -export async function getTargetBuildInfo(updateChannel: string, isFromSettingsChange: boolean): Promise { - const builds: Build[] | undefined = await getReleaseJson(); - if (!builds || builds.length === 0) { - return undefined; - } - - const userVersion: PackageVersion = new PackageVersion(util.packageJson.version); - const targetBuild: Build | undefined = getTargetBuild(builds, userVersion, updateChannel, isFromSettingsChange); - if (targetBuild === undefined) { - // no action - telemetry.logLanguageServerEvent("UpgradeCheck", { "action": "none" }); - } else if (userVersion.isExtensionVersionGreaterThan(new PackageVersion(targetBuild.name))) { - // downgrade - telemetry.logLanguageServerEvent("UpgradeCheck", { "action": "downgrade", "newVersion": targetBuild.name }); - } else { - // upgrade - telemetry.logLanguageServerEvent("UpgradeCheck", { "action": "upgrade", "newVersion": targetBuild.name }); - } - - if (!targetBuild) { - return undefined; - } - const platformInfo: PlatformInformation = await PlatformInformation.GetPlatformInformation(); - const vsixName: string = vsixNameForPlatform(platformInfo); - const downloadUrl: string = getVsixDownloadUrl(targetBuild, vsixName); - if (!downloadUrl) { - return undefined; - } - return { downloadUrl: downloadUrl, name: targetBuild.name }; - -} - -/** - * Determines whether there exists a Build in the given Build[] that should be installed. - * @param builds The GitHub release list parsed as an array of Builds. - * @param userVersion The verion of the extension that the user is running. - * @param updateChannel The user's updateChannel setting. - * @param isFromSettingsChange True if the invocation is the result of a settings change. - * @return The Build if the user should update to it, otherwise undefined. - */ -export function getTargetBuild(builds: Build[], userVersion: PackageVersion, updateChannel: string, isFromSettingsChange: boolean): Build | undefined { - if (!isFromSettingsChange && !vscode.workspace.getConfiguration("extensions", null).get("autoUpdate")) { - return undefined; - } - const latestVersionOnline: PackageVersion = new PackageVersion(builds[0].name); - // Allows testing pre-releases without accidentally downgrading to the latest version - if ((!testingInsidersVsixInstall && userVersion.suffix && userVersion.suffix !== 'insiders') || - userVersion.isExtensionVersionGreaterThan(latestVersionOnline)) { - return undefined; - } - - // Get predicates to determine the build to install, if any - let needsUpdate: (installed: PackageVersion, target: PackageVersion) => boolean; - let useBuild: (build: Build) => boolean; - if (updateChannel === 'Insiders') { - needsUpdate = (installed: PackageVersion, target: PackageVersion) => testingInsidersVsixInstall || (!target.isEqual(installed)); - // Check if the assets are available - useBuild = isValidBuild; - } else if (updateChannel === 'Default') { - // If the updateChannel switches from 'Insiders' to 'Default', a downgrade to the latest non-insiders release is needed. - needsUpdate = function(installed: PackageVersion, target: PackageVersion): boolean { - return installed.isExtensionVersionGreaterThan(target); }; - // Look for the latest non-insiders released build - useBuild = (build: Build): boolean => build.name.indexOf('-') === -1 && isValidBuild(build); - } else { - throw new Error('Incorrect updateChannel setting provided'); - } - - // Get the build to install - const targetBuild: Build | undefined = builds.find(useBuild); - if (!targetBuild) { - throw new Error('Failed to determine installation candidate'); - } - - // Check current version against target's version to determine if the installation should happen - const targetVersion: PackageVersion = new PackageVersion(targetBuild.name); - if (needsUpdate(userVersion, targetVersion)) { - return targetBuild; - } else { - return undefined; - } -} - -interface Rate { - remaining: number; -} - -interface RateLimit { - rate: Rate; -} - -function isRate(input: any): input is Rate { - return input && util.isNumber(input.remaining); -} - -function isRateLimit(input: any): input is RateLimit { - return input && isRate(input.rate); -} - -async function getRateLimit(): Promise { - const header: OutgoingHttpHeaders = { 'User-Agent': 'vscode-cpptools' }; - try { - const data: string = await util.downloadFileToStr('https://api.github.com/rate_limit', header); - if (!data) { - return undefined; - } - let rateLimit: any; - try { - rateLimit = JSON.parse(data); - } catch (error) { - throw new Error('Failed to parse rate limit JSON'); - } - - if (isRateLimit(rateLimit)) { - return rateLimit; - } else { - throw new Error('Rate limit JSON is not of type RateLimit'); - } - - } catch (errJS) { - const err: NodeJS.ErrnoException = errJS as NodeJS.ErrnoException; - if (err && err.code && err.code !== "ENOENT") { - // Only throw if the user is connected to the Internet. - throw new Error('Failed to download rate limit JSON'); - } - } -} - -async function rateLimitExceeded(): Promise { - const rateLimit: RateLimit | undefined = await getRateLimit(); - return rateLimit !== undefined && rateLimit.rate.remaining <= 0; -} - -/** - * Download and parse the release list JSON from the GitHub API into a Build[]. - * @return Information about the released builds of the C/C++ extension. - */ -async function getReleaseJson(): Promise { - if (await rateLimitExceeded()) { - throw new Error('Failed to stay within GitHub API rate limit'); - } - - // Download release JSON - const releaseUrl: string = 'https://api.github.com/repos/Microsoft/vscode-cpptools/releases'; - const header: OutgoingHttpHeaders = { 'User-Agent': 'vscode-cpptools' }; - - try { - const data: string = await util.downloadFileToStr(releaseUrl, header); - if (!data) { - return undefined; - } - - // Parse the file - let releaseJson: any; - try { - releaseJson = JSON.parse(data); - } catch (error) { - throw new Error('Failed to parse release JSON'); - } - - // Find the latest released builds. - const builds: Build[] = getArrayOfBuilds(releaseJson); - if (!builds || builds.length === 0) { - throw new Error('Release JSON is not of type Build[]'); - } else { - return builds; - } - } catch (errJS) { - const err: NodeJS.ErrnoException = errJS as NodeJS.ErrnoException; - if (err && err.code && err.code !== "ENOENT") { - // Only throw if the user is connected to the Internet. - throw new Error('Failed to download release JSON'); - } - } -} diff --git a/Extension/src/packageVersion.ts b/Extension/src/packageVersion.ts index e0e61d4ef7..1fbfe046ff 100644 --- a/Extension/src/packageVersion.ts +++ b/Extension/src/packageVersion.ts @@ -54,10 +54,6 @@ export class PackageVersion { return this.isGreaterThan(other, 'insider') || this.isGreaterThan(other, 'exploration'); } - public isExtensionVersionGreaterThan(other: PackageVersion): boolean { - return this.isGreaterThan(other, 'insiders'); - } - public isMajorMinorPatchGreaterThan(other: PackageVersion): boolean { return this.isGreaterThan(other, ""); } From bacd302420b66abfa475ffaa4a0ab10e6169f827 Mon Sep 17 00:00:00 2001 From: Colen Garoutte-Carson Date: Thu, 9 Dec 2021 13:25:19 -0800 Subject: [PATCH 07/15] Temporarily disable integration tests --- .github/workflows/ci_linux.yml | 10 +++++----- .github/workflows/ci_mac.yml | 10 +++++----- .github/workflows/ci_windows.yml | 6 +++--- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/ci_linux.yml b/.github/workflows/ci_linux.yml index 0192ef79c2..d69442e9ed 100644 --- a/.github/workflows/ci_linux.yml +++ b/.github/workflows/ci_linux.yml @@ -40,8 +40,8 @@ jobs: run: yarn run unitTests working-directory: Extension - - name: Run languageServer integration tests - uses: GabrielBB/xvfb-action@v1.4 - with: - run: yarn run integrationTests - working-directory: Extension +# - name: Run languageServer integration tests +# uses: GabrielBB/xvfb-action@v1.4 +# with: +# run: yarn run integrationTests +# working-directory: Extension diff --git a/.github/workflows/ci_mac.yml b/.github/workflows/ci_mac.yml index e614d02d90..31c61684d2 100644 --- a/.github/workflows/ci_mac.yml +++ b/.github/workflows/ci_mac.yml @@ -40,8 +40,8 @@ jobs: run: yarn run unitTests working-directory: Extension - - name: Run languageServer integration tests - uses: GabrielBB/xvfb-action@v1.4 - with: - run: yarn run integrationTests - working-directory: Extension +# - name: Run languageServer integration tests +# uses: GabrielBB/xvfb-action@v1.4 +# with: +# run: yarn run integrationTests +# working-directory: Extension diff --git a/.github/workflows/ci_windows.yml b/.github/workflows/ci_windows.yml index 3c16c93cac..ec0697408a 100644 --- a/.github/workflows/ci_windows.yml +++ b/.github/workflows/ci_windows.yml @@ -38,6 +38,6 @@ jobs: run: yarn run unitTests working-directory: Extension - - name: Run languageServer integration tests - run: yarn run integrationTests - working-directory: Extension +# - name: Run languageServer integration tests +# run: yarn run integrationTests +# working-directory: Extension From a364f90d5c28f5f381f92d668c3c298c4b93a1da Mon Sep 17 00:00:00 2001 From: Colen Garoutte-Carson Date: Thu, 9 Dec 2021 13:48:09 -0800 Subject: [PATCH 08/15] Use release.flag or insider.flag file existance to determine release type --- Extension/src/telemetry.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Extension/src/telemetry.ts b/Extension/src/telemetry.ts index f883fabfdb..a014dd5f3a 100644 --- a/Extension/src/telemetry.ts +++ b/Extension/src/telemetry.ts @@ -7,6 +7,7 @@ import TelemetryReporter from 'vscode-extension-telemetry'; import { getExperimentationServiceAsync, IExperimentationService, IExperimentationTelemetry, TargetPopulation } from 'vscode-tas-client'; import * as util from './common'; +import { getExtensionFilePath } from './common'; import { PackageVersion } from './packageVersion'; interface IPackageInfo { @@ -64,11 +65,14 @@ export function activate(): void { const packageInfo: IPackageInfo = getPackageInfo(); if (packageInfo) { let targetPopulation: TargetPopulation; - const userVersion: PackageVersion = new PackageVersion(packageInfo.version); - if (!userVersion.suffix) { - targetPopulation = TargetPopulation.Public; - } else if (userVersion.suffix === "insiders") { + + // If insiders.flag is present, consider this an insiders build. + // If release.flag is present, consider this a release build. + // Otherwise, consider this an internal build. + if (util.checkFileExistsSync(getExtensionFilePath("insiders.flag"))) { targetPopulation = TargetPopulation.Insiders; + } else if (util.checkFileExistsSync(getExtensionFilePath("release.flag"))) { + targetPopulation = TargetPopulation.Public; } else { targetPopulation = TargetPopulation.Internal; } From 2d5746bc1a85118189336c29006dc950f69013a5 Mon Sep 17 00:00:00 2001 From: Colen Garoutte-Carson Date: Thu, 9 Dec 2021 13:51:45 -0800 Subject: [PATCH 09/15] Fix lint issue --- Extension/src/telemetry.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Extension/src/telemetry.ts b/Extension/src/telemetry.ts index a014dd5f3a..0d7ce1edf6 100644 --- a/Extension/src/telemetry.ts +++ b/Extension/src/telemetry.ts @@ -7,8 +7,6 @@ import TelemetryReporter from 'vscode-extension-telemetry'; import { getExperimentationServiceAsync, IExperimentationService, IExperimentationTelemetry, TargetPopulation } from 'vscode-tas-client'; import * as util from './common'; -import { getExtensionFilePath } from './common'; -import { PackageVersion } from './packageVersion'; interface IPackageInfo { name: string; @@ -69,9 +67,9 @@ export function activate(): void { // If insiders.flag is present, consider this an insiders build. // If release.flag is present, consider this a release build. // Otherwise, consider this an internal build. - if (util.checkFileExistsSync(getExtensionFilePath("insiders.flag"))) { + if (util.checkFileExistsSync(util.getExtensionFilePath("insiders.flag"))) { targetPopulation = TargetPopulation.Insiders; - } else if (util.checkFileExistsSync(getExtensionFilePath("release.flag"))) { + } else if (util.checkFileExistsSync(util.getExtensionFilePath("release.flag"))) { targetPopulation = TargetPopulation.Public; } else { targetPopulation = TargetPopulation.Internal; From bc121653117a164649e455856f9e5a503ec4baca Mon Sep 17 00:00:00 2001 From: Colen Garoutte-Carson Date: Thu, 9 Dec 2021 15:22:34 -0800 Subject: [PATCH 10/15] Remove updowngrade tests --- Extension/test/unitTests/updowngrade.test.ts | 227 ------------------- 1 file changed, 227 deletions(-) delete mode 100644 Extension/test/unitTests/updowngrade.test.ts diff --git a/Extension/test/unitTests/updowngrade.test.ts b/Extension/test/unitTests/updowngrade.test.ts deleted file mode 100644 index c3480bfde5..0000000000 --- a/Extension/test/unitTests/updowngrade.test.ts +++ /dev/null @@ -1,227 +0,0 @@ -/* -------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All Rights Reserved. - * See 'LICENSE' in the project root for license information. - * ------------------------------------------------------------------------------------------ */ - -import * as assert from "assert"; -import { Build, Asset, getTargetBuild } from "../../src/githubAPI"; -import { PackageVersion } from '../../src/packageVersion'; - -suite("UpgradeDowngrade", () => { - - const asset_win32: Asset = {name: "cpptools-win32.vsix", browser_download_url: "https://github.com/microsoft/vscode-cpptools/releases/download/0.27.0/cpptools-win32.vsix"}; - const asset_linux: Asset = {name: "cpptools-linux.vsix", browser_download_url: "https://github.com/microsoft/vscode-cpptools/releases/download/0.27.0/cpptools-linux.vsix"}; - const asset_osx: Asset = {name: "cpptools-osx.vsix", browser_download_url: "https://github.com/microsoft/vscode-cpptools/releases/download/0.27.0/cpptools-osx.vsix"}; - const three_assets: Asset[] = [asset_win32, asset_linux, asset_osx]; - - const release1patch: string = "0.28.1"; - const release1: string = "0.28.0"; - const insider3: string = "0.28.0-insiders3"; - const insider2: string = "0.28.0-insiders2"; - const insider1: string = "0.28.0-insiders"; - const release0patch: string = "0.27.1"; - const release0: string = "0.27.0"; - - suite("DefaultChannel", () => { - const updateChannel: string = "Default"; - // When updateChannel switches from 'Insiders' to 'Default', the only possible action is to downgrade. - suite("Downgrade", () => { - test("Insiders to Release", () => { - const builds: Build[] = [{ - name: insider3, assets: []}, { - name: insider2, assets: three_assets}, { - name: insider1, assets: three_assets}, { - name: release0patch, assets: []}, { - name: release0, assets: three_assets}]; - - const userVersion: PackageVersion = new PackageVersion(insider2); - const targetBuild: Build | undefined = getTargetBuild(builds, userVersion, updateChannel, false); - assert.equal(targetBuild.name, release0); - }); - }); - suite("Internal Testing, no Downgrade", () => { - test("Insider to Release", () => { - const builds: Build[] = [{ - name: release0, assets: three_assets}]; - - const userVersion: PackageVersion = new PackageVersion(insider1); - const targetBuild: Build | undefined = getTargetBuild(builds, userVersion, updateChannel, false); - assert.equal(targetBuild, undefined); - }); - test("Insider to Insider", () => { - const builds: Build[] = [{ - name: insider2, assets: three_assets}, { - name: insider1, assets: three_assets}, { - name: release0, assets: three_assets}]; - - const userVersion: PackageVersion = new PackageVersion(insider3); - const targetBuild: Build | undefined = getTargetBuild(builds, userVersion, updateChannel, false); - assert.equal(targetBuild, undefined); - }); - test("Release to Insider (main)", () => { - const builds: Build[] = [{ - name: insider3, assets: three_assets}, { - name: insider2, assets: three_assets}, { - name: insider1, assets: three_assets}, { - name: release0, assets: three_assets}]; - // In internal testing, the name of the release has a "-main" at the end of it. - const userVersion: PackageVersion = new PackageVersion(release1 + "-main"); - const targetBuild: Build | undefined = getTargetBuild(builds, userVersion, updateChannel, false); - assert.equal(targetBuild, undefined); - }); - test("Release to Insider", () => { - const builds: Build[] = [{ - name: insider3, assets: three_assets}, { - name: insider2, assets: three_assets}, { - name: insider1, assets: three_assets}, { - name: release0, assets: three_assets}]; - const userVersion: PackageVersion = new PackageVersion(release1); - const targetBuild: Build | undefined = getTargetBuild(builds, userVersion, updateChannel, false); - assert.equal(targetBuild, undefined); - }); - }); - }); - - suite("InsidersChannel", () => { - const updateChannel: string = "Insiders"; - suite("Downgrade", () => { - suite("Internal Testing, no Downgrade", () => { - test("Insider to Release", () => { - const builds: Build[] = [{ - name: release0, assets: three_assets}]; - - const userVersion: PackageVersion = new PackageVersion(insider1); - const targetBuild: Build | undefined = getTargetBuild(builds, userVersion, updateChannel, false); - assert.equal(targetBuild, undefined); - }); - test("Insider to Insider", () => { - const builds: Build[] = [{ - name: insider2, assets: three_assets}, { - name: insider1, assets: three_assets}, { - name: release0, assets: three_assets}]; - - const userVersion: PackageVersion = new PackageVersion(insider3); - const targetBuild: Build | undefined = getTargetBuild(builds, userVersion, updateChannel, false); - assert.equal(targetBuild, undefined); - }); - test("Release to Insider (main)", () => { - const builds: Build[] = [{ - name: insider3, assets: three_assets}, { - name: insider2, assets: three_assets}, { - name: insider1, assets: three_assets}, { - name: release0, assets: three_assets}]; - // In internal testing, the name of the release has a "-main" at the end of it. - const userVersion: PackageVersion = new PackageVersion(release1 + "-main"); - const targetBuild: Build | undefined = getTargetBuild(builds, userVersion, updateChannel, false); - assert.equal(targetBuild, undefined); - }); - test("Release to Insider", () => { - const builds: Build[] = [{ - name: insider3, assets: three_assets}, { - name: insider2, assets: three_assets}, { - name: insider1, assets: three_assets}, { - name: release0, assets: three_assets}]; - const userVersion: PackageVersion = new PackageVersion(release1); - const targetBuild: Build | undefined = getTargetBuild(builds, userVersion, updateChannel, false); - assert.equal(targetBuild, undefined); - }); - }); - - suite("Insider Users, Downgrade", () => { - test("Insider to Release", () => { - const builds: Build[] = [{ - name: insider3, assets: []}, { - name: insider2, assets: []}, { - name: insider1, assets: []}, { - name: release0patch, assets: []}, { - name: release0, assets: three_assets}]; - - const userVersion: PackageVersion = new PackageVersion(insider3); - const targetBuild: Build | undefined = getTargetBuild(builds, userVersion, updateChannel, false); - assert.equal(targetBuild.name, release0); - }); - test("Insider to Insider", () => { - const builds: Build[] = [{ - name: insider3, assets: []}, { - name: insider2, assets: []}, { - name: insider1, assets: three_assets}, { - name: release0, assets: three_assets}]; - - const userVersion: PackageVersion = new PackageVersion(insider3); - const targetBuild: Build | undefined = getTargetBuild(builds, userVersion, updateChannel, false); - assert.equal(targetBuild.name, insider1); - }); - }); - }); - - suite("Upgrade", () => { - suite("Automatic Upgrade", () => { - test("Release to Release", () => { - const builds: Build[] = [{ - name: release1patch, assets: []}, { - name: release1, assets: three_assets}, { - name: insider3, assets: three_assets}, { - name: insider2, assets: three_assets}]; - - const userVersion: PackageVersion = new PackageVersion(release0); - const targetBuild: Build | undefined = getTargetBuild(builds, userVersion, updateChannel, false); - assert.equal(targetBuild.name, release1); - }); - test("Insider to Release", () => { - const builds: Build[] = [{ - name: release1, assets: three_assets}, { - name: insider3, assets: three_assets}, { - name: insider2, assets: three_assets}]; - - const userVersion: PackageVersion = new PackageVersion(insider2); - const targetBuild: Build | undefined = getTargetBuild(builds, userVersion, updateChannel, false); - assert.equal(targetBuild.name, release1); - }); - }); - - suite("Asset Checking Upgrade", () => { - test("Release to Insider, Upgrade", () => { - const builds: Build[] = [{ - name: insider2, assets: []}, { - name: insider1, assets: three_assets}, { - name: release0, assets: three_assets}]; - - const userVersion: PackageVersion = new PackageVersion(release0); - const targetBuild: Build | undefined = getTargetBuild(builds, userVersion, updateChannel, false); - assert.equal(targetBuild.name, insider1); - }); - test("Release to Insider, no Upgrade", () => { - const builds: Build[] = [{ - name: insider2, assets: []}, { - name: insider1, assets: []}, { - name: release0, assets: three_assets}]; - - const userVersion: PackageVersion = new PackageVersion(release0); - const targetBuild: Build | undefined = getTargetBuild(builds, userVersion, updateChannel, false); - assert.equal(targetBuild, undefined); - }); - test("Insider to Insider, Upgrade", () => { - const builds: Build[] = [{ - name: insider3, assets: []}, { - name: insider2, assets: three_assets}, { - name: insider1, assets: three_assets}, { - name: release0, assets: three_assets}]; - - const userVersion: PackageVersion = new PackageVersion(insider1); - const targetBuild: Build | undefined = getTargetBuild(builds, userVersion, updateChannel, false); - assert.equal(targetBuild.name, insider2); - }); - test("Insider to Insider, no Upgrade", () => { - const builds: Build[] = [{ - name: insider3, assets: []}, { - name: insider2, assets: three_assets}, { - name: release0, assets: three_assets}]; - - const userVersion: PackageVersion = new PackageVersion(insider2); - const targetBuild: Build | undefined = getTargetBuild(builds, userVersion, updateChannel, false); - assert.equal(targetBuild, undefined); - }); - }); - }); - }); -}); From 563e170394f9c9dc0e93ef3f9e88519887ac1a5f Mon Sep 17 00:00:00 2001 From: Colen Garoutte-Carson Date: Thu, 9 Dec 2021 15:44:15 -0800 Subject: [PATCH 11/15] Address PR feedback --- Extension/package.json | 70 +++++++++++++++++++------------------- Extension/src/common.ts | 13 +++++++ Extension/src/main.ts | 10 ++++-- Extension/src/telemetry.ts | 13 +------ 4 files changed, 57 insertions(+), 49 deletions(-) diff --git a/Extension/package.json b/Extension/package.json index 5105b64f3f..9a107af52b 100644 --- a/Extension/package.json +++ b/Extension/package.json @@ -45,41 +45,41 @@ "virtualWorkspaces": false }, "activationEvents": [ - "onLanguage:c", - "onLanguage:cpp", - "onLanguage:cuda-cpp", - "onCommand:extension.pickNativeProcess", - "onCommand:extension.pickRemoteNativeProcess", - "onCommand:C_Cpp.BuildAndDebugActiveFile", - "onCommand:C_Cpp.RestartIntelliSenseForFile", - "onCommand:C_Cpp.ConfigurationEditJSON", - "onCommand:C_Cpp.ConfigurationEditUI", - "onCommand:C_Cpp.ConfigurationSelect", - "onCommand:C_Cpp.ConfigurationProviderSelect", - "onCommand:C_Cpp.SwitchHeaderSource", - "onCommand:C_Cpp.EnableErrorSquiggles", - "onCommand:C_Cpp.DisableErrorSquiggles", - "onCommand:C_Cpp.ToggleIncludeFallback", - "onCommand:C_Cpp.ToggleDimInactiveRegions", - "onCommand:C_Cpp.ResetDatabase", - "onCommand:C_Cpp.TakeSurvey", - "onCommand:C_Cpp.LogDiagnostics", - "onCommand:C_Cpp.RescanWorkspace", - "onCommand:C_Cpp.VcpkgClipboardInstallSuggested", - "onCommand:C_Cpp.VcpkgOnlineHelpSuggested", - "onCommand:C_Cpp.GenerateEditorConfig", - "onCommand:C_Cpp.GoToNextDirectiveInGroup", - "onCommand:C_Cpp.GoToPrevDirectiveInGroup", - "onCommand:C_Cpp.CheckForCompiler", - "onCommand:C_Cpp.RunCodeAnalysisOnActiveFile", - "onCommand:C_Cpp.RunCodeAnalysisOnOpenFiles", - "onCommand:C_Cpp.RunCodeAnalysisOnAllFiles", - "onCommand:C_Cpp.ClearCodeAnalysisSquiggles", - "onDebugInitialConfigurations", - "onDebugResolve:cppdbg", - "onDebugResolve:cppvsdbg", - "workspaceContains:/.vscode/c_cpp_properties.json", - "onFileSystem:cpptools-schema" + "onLanguage:c", + "onLanguage:cpp", + "onLanguage:cuda-cpp", + "onCommand:extension.pickNativeProcess", + "onCommand:extension.pickRemoteNativeProcess", + "onCommand:C_Cpp.BuildAndDebugActiveFile", + "onCommand:C_Cpp.RestartIntelliSenseForFile", + "onCommand:C_Cpp.ConfigurationEditJSON", + "onCommand:C_Cpp.ConfigurationEditUI", + "onCommand:C_Cpp.ConfigurationSelect", + "onCommand:C_Cpp.ConfigurationProviderSelect", + "onCommand:C_Cpp.SwitchHeaderSource", + "onCommand:C_Cpp.EnableErrorSquiggles", + "onCommand:C_Cpp.DisableErrorSquiggles", + "onCommand:C_Cpp.ToggleIncludeFallback", + "onCommand:C_Cpp.ToggleDimInactiveRegions", + "onCommand:C_Cpp.ResetDatabase", + "onCommand:C_Cpp.TakeSurvey", + "onCommand:C_Cpp.LogDiagnostics", + "onCommand:C_Cpp.RescanWorkspace", + "onCommand:C_Cpp.VcpkgClipboardInstallSuggested", + "onCommand:C_Cpp.VcpkgOnlineHelpSuggested", + "onCommand:C_Cpp.GenerateEditorConfig", + "onCommand:C_Cpp.GoToNextDirectiveInGroup", + "onCommand:C_Cpp.GoToPrevDirectiveInGroup", + "onCommand:C_Cpp.CheckForCompiler", + "onCommand:C_Cpp.RunCodeAnalysisOnActiveFile", + "onCommand:C_Cpp.RunCodeAnalysisOnOpenFiles", + "onCommand:C_Cpp.RunCodeAnalysisOnAllFiles", + "onCommand:C_Cpp.ClearCodeAnalysisSquiggles", + "onDebugInitialConfigurations", + "onDebugResolve:cppdbg", + "onDebugResolve:cppvsdbg", + "workspaceContains:/.vscode/c_cpp_properties.json", + "onFileSystem:cpptools-schema" ], "main": "./dist/main", "contributes": { diff --git a/Extension/src/common.ts b/Extension/src/common.ts index 503ac03796..e36fc82f2f 100644 --- a/Extension/src/common.ts +++ b/Extension/src/common.ts @@ -21,6 +21,7 @@ import { lookupString } from './nativeStrings'; import * as nls from 'vscode-nls'; import { Readable } from 'stream'; import * as jsonc from 'comment-json'; +import { TargetPopulation } from 'vscode-tas-client'; nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })(); const localize: nls.LocalizeFunc = nls.loadMessageBundle(); @@ -1233,3 +1234,15 @@ export function findPowerShell(): string | undefined { } } } + +export function getTargetPopulation(): TargetPopulation { + // If insiders.flag is present, consider this an insiders build. + // If release.flag is present, consider this a release build. + // Otherwise, consider this an internal build. + if (checkFileExistsSync(getExtensionFilePath("insiders.flag"))) { + return TargetPopulation.Insiders; + } else if (checkFileExistsSync(getExtensionFilePath("release.flag"))) { + return TargetPopulation.Public; + } + return TargetPopulation.Internal; +} diff --git a/Extension/src/main.ts b/Extension/src/main.ts index 15ed3f31a0..1a6d53f790 100644 --- a/Extension/src/main.ts +++ b/Extension/src/main.ts @@ -16,6 +16,7 @@ import { CppToolsApi, CppToolsExtension } from 'vscode-cpptools'; import { PlatformInformation } from './platform'; import { CppTools1 } from './cppTools1'; import { CppSettings } from './LanguageServer/settings'; +import { PersistentState } from './LanguageServer/persistentState'; const cppTools: CppTools1 = new CppTools1(); let languageServiceDisabled: boolean = false; @@ -48,8 +49,13 @@ export async function activate(context: vscode.ExtensionContext): Promise = new PersistentState("CPP.installedVersion", undefined); + if (!installedVersion.Value || installedVersion.Value !== util.packageJson.version) { + installedVersion.Value = util.packageJson.version; + await makeBinariesExecutable(); + sendTelemetry(info); + } // Notify users if debugging may not be supported on their OS. util.checkDistro(info); diff --git a/Extension/src/telemetry.ts b/Extension/src/telemetry.ts index 0d7ce1edf6..36a4812471 100644 --- a/Extension/src/telemetry.ts +++ b/Extension/src/telemetry.ts @@ -62,18 +62,7 @@ export function activate(): void { if (util.extensionContext) { const packageInfo: IPackageInfo = getPackageInfo(); if (packageInfo) { - let targetPopulation: TargetPopulation; - - // If insiders.flag is present, consider this an insiders build. - // If release.flag is present, consider this a release build. - // Otherwise, consider this an internal build. - if (util.checkFileExistsSync(util.getExtensionFilePath("insiders.flag"))) { - targetPopulation = TargetPopulation.Insiders; - } else if (util.checkFileExistsSync(util.getExtensionFilePath("release.flag"))) { - targetPopulation = TargetPopulation.Public; - } else { - targetPopulation = TargetPopulation.Internal; - } + const targetPopulation: TargetPopulation = util.getTargetPopulation(); experimentationTelemetry = new ExperimentationTelemetry(new TelemetryReporter(packageInfo.name, packageInfo.version, appInsightsKey)); initializationPromise = getExperimentationServiceAsync(packageInfo.name, packageInfo.version, targetPopulation, experimentationTelemetry, util.extensionContext.globalState); } From 14eddbf327fa3c5c9a884f0c378d98a05a7e79e8 Mon Sep 17 00:00:00 2001 From: Colen Garoutte-Carson Date: Tue, 14 Dec 2021 13:42:00 -0800 Subject: [PATCH 12/15] Always make binaries executable --- Extension/src/main.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Extension/src/main.ts b/Extension/src/main.ts index 1a6d53f790..383d840dd3 100644 --- a/Extension/src/main.ts +++ b/Extension/src/main.ts @@ -53,10 +53,13 @@ export async function activate(context: vscode.ExtensionContext): Promise = new PersistentState("CPP.installedVersion", undefined); if (!installedVersion.Value || installedVersion.Value !== util.packageJson.version) { installedVersion.Value = util.packageJson.version; - await makeBinariesExecutable(); sendTelemetry(info); } + // Always attempt to make the binaries executable, not just when installedVersion changes. + // The user may have uninstalled and reinstalled the same version. + await makeBinariesExecutable(); + // Notify users if debugging may not be supported on their OS. util.checkDistro(info); From 11a3df27736a180c3896ffdd86db9f7c93343ddd Mon Sep 17 00:00:00 2001 From: Colen Garoutte-Carson Date: Tue, 14 Dec 2021 13:50:04 -0800 Subject: [PATCH 13/15] Cleanup --- Extension/src/LanguageServer/client.ts | 6 -- Extension/src/packageVersion.ts | 94 -------------------------- 2 files changed, 100 deletions(-) delete mode 100644 Extension/src/packageVersion.ts diff --git a/Extension/src/LanguageServer/client.ts b/Extension/src/LanguageServer/client.ts index 30a5e4c50f..c6d7782d28 100644 --- a/Extension/src/LanguageServer/client.ts +++ b/Extension/src/LanguageServer/client.ts @@ -1045,9 +1045,6 @@ export class DefaultClient implements Client { } } catch (err) { this.isSupported = false; // Running on an OS we don't support yet. - console.log("---------------------"); - console.log(String(err)); - console.log("---------------------"); if (!failureMessageShown) { failureMessageShown = true; vscode.window.showErrorMessage(localize("unable.to.start", "Unable to start the C/C++ language server. IntelliSense features will be disabled. Error: {0}", String(err))); @@ -1057,9 +1054,6 @@ export class DefaultClient implements Client { } catch (errJS) { const err: NodeJS.ErrnoException = errJS as NodeJS.ErrnoException; this.isSupported = false; // Running on an OS we don't support yet. - console.log("---------------------"); - console.log(String(err)); - console.log("---------------------"); if (!failureMessageShown) { failureMessageShown = true; let additionalInfo: string; diff --git a/Extension/src/packageVersion.ts b/Extension/src/packageVersion.ts deleted file mode 100644 index 1fbfe046ff..0000000000 --- a/Extension/src/packageVersion.ts +++ /dev/null @@ -1,94 +0,0 @@ -/* -------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All Rights Reserved. - * See 'LICENSE' in the project root for license information. - * ------------------------------------------------------------------------------------------ */ -'use strict'; - -export class PackageVersion { - major: number; - minor: number; - patch: number; - suffix?: string; - suffixVersion: number; - - constructor(version: string) { - const tokens: string[] = version.split(new RegExp('[-\\.]', 'g')); // Match against dots and dashes - if (tokens.length < 3) { - throw new Error(`Failed to parse version string: ${version}`); - } - - this.major = parseInt(tokens[0]); - this.minor = parseInt(tokens[1]); - this.patch = parseInt(tokens[2]); - - if (tokens.length > 3) { - const firstDigitOffset: number = tokens[3].search(new RegExp(/(\d)/)); // Find first occurrence of 0-9 - if (firstDigitOffset !== -1) { - this.suffix = tokens[3].substring(0, firstDigitOffset); - this.suffixVersion = parseInt(tokens[3].substring(firstDigitOffset)); - } else { - this.suffix = tokens[3]; - this.suffixVersion = 1; - } - } else { - this.suffix = undefined; - this.suffixVersion = 0; - } - - if (this.major === undefined - || this.major === null - || this.minor === undefined - || this.minor === null - || this.patch === undefined - || this.patch === null) { - throw new Error(`Failed to parse version string: ${version}`); - } - } - - public isEqual(other: PackageVersion): boolean { - return this.major === other.major && this.minor === other.minor && this.patch === other.patch && - this.suffix === other.suffix && this.suffixVersion === other.suffixVersion; - } - - public isVsCodeVersionGreaterThan(other: PackageVersion): boolean { - return this.isGreaterThan(other, 'insider') || this.isGreaterThan(other, 'exploration'); - } - - public isMajorMinorPatchGreaterThan(other: PackageVersion): boolean { - return this.isGreaterThan(other, ""); - } - - private isGreaterThan(other: PackageVersion, suffixStr: string): boolean { - if (suffixStr && ((this.suffix && !this.suffix.startsWith(suffixStr)) || (other.suffix && !other.suffix.startsWith(suffixStr)))) { - return false; - } - - let diff: number = this.major - other.major; - if (diff) { - return diff > 0; - } else { - diff = this.minor - other.minor; - if (diff) { - return diff > 0; - } else { - diff = this.patch - other.patch; - if (diff) { - return diff > 0; - } else { - // When suffixStr is empty, only the major/minor/patch components of the version are being compared. - if (!suffixStr) { - return false; - } - if (this.suffix) { - if (!other.suffix) { - return false; - } - return (this.suffixVersion > other.suffixVersion); - } else { - return other.suffix ? true : false; - } - } - } - } - } -} From f01c5527c26ee8a18db68b53dba736224d0ac5e1 Mon Sep 17 00:00:00 2001 From: Colen Garoutte-Carson Date: Tue, 14 Dec 2021 16:56:22 -0800 Subject: [PATCH 14/15] Put updateChannel back in as deprecated. Provide UI for updateChannel migration. Always send `acquisition` telemetry on activation. --- Extension/package.json | 11 +++++ Extension/package.nls.json | 1 + Extension/src/LanguageServer/extension.ts | 7 ++++ Extension/src/LanguageServer/settings.ts | 1 + Extension/src/main.ts | 49 ++++++++++++++++++++--- 5 files changed, 63 insertions(+), 6 deletions(-) diff --git a/Extension/package.json b/Extension/package.json index 9a107af52b..8e8ea33f00 100644 --- a/Extension/package.json +++ b/Extension/package.json @@ -2472,6 +2472,17 @@ "markdownDescription": "%c_cpp.configuration.default.enableConfigurationSquiggles.markdownDescription%", "scope": "resource" }, + "C_Cpp.updateChannel": { + "type": "string", + "enum": [ + "Default", + "Insiders" + ], + "default": "Default", + "markdownDescription": "%c_cpp.configuration.updateChannel.markdownDescription%", + "scope": "application", + "deprecationMessage": "%c_cpp.configuration.updateChannel.deprecationMessage%" + }, "C_Cpp.experimentalFeatures": { "type": "string", "enum": [ diff --git a/Extension/package.nls.json b/Extension/package.nls.json index 7360d2ffb1..b0d1e2c9ef 100644 --- a/Extension/package.nls.json +++ b/Extension/package.nls.json @@ -194,6 +194,7 @@ "c_cpp.configuration.default.enableConfigurationSquiggles.markdownDescription": { "message": "Controls whether the extension will report errors detected in `c_cpp_properties.json`.", "comment": [ "Markdown text between `` should not be translated or localized (they represent literal text) and the capitalization, spacing, and punctuation (including the ``) should not be altered." ] }, "c_cpp.configuration.default.customConfigurationVariables.markdownDescription": { "message": "The value to use in a configuration if `customConfigurationVariables` is not set, or the values to insert if `${default}` is present as a key in `customConfigurationVariables`.", "comment": [ "Markdown text between `` should not be translated or localized (they represent literal text) and the capitalization, spacing, and punctuation (including the ``) should not be altered." ] }, "c_cpp.configuration.updateChannel.markdownDescription": { "message": "Set to `Insiders` to automatically download and install the latest Insiders builds of the extension, which include upcoming features and bug fixes.", "comment": [ "Markdown text between `` should not be translated or localized (they represent literal text) and the capitalization, spacing, and punctuation (including the ``) should not be altered." ] }, + "c_cpp.configuration.updateChannel.deprecationMessage": "This setting is deprecated. Pre-release extensions are now available via the Marketplace.", "c_cpp.configuration.experimentalFeatures.description": "Controls whether \"experimental\" features are usable.", "c_cpp.configuration.suggestSnippets.markdownDescription": { "message": "If `true`, snippets are provided by the language server.", "comment": [ "Markdown text between `` should not be translated or localized (they represent literal text) and the capitalization, spacing, and punctuation (including the ``) should not be altered." ] }, "c_cpp.configuration.enhancedColorization.markdownDescription": { "message": "If enabled, code is colorized based on IntelliSense. This setting only applies if `#C_Cpp.intelliSenseEngine#` is set to `Default`.", "comment": [ "Markdown text between `` should not be translated or localized (they represent literal text) and the capitalization, spacing, and punctuation (including the ``) should not be altered." ] }, diff --git a/Extension/src/LanguageServer/extension.ts b/Extension/src/LanguageServer/extension.ts index be995ea4bd..604b6dde6e 100644 --- a/Extension/src/LanguageServer/extension.ts +++ b/Extension/src/LanguageServer/extension.ts @@ -24,6 +24,7 @@ import * as yauzl from 'yauzl'; import { Readable } from 'stream'; import * as nls from 'vscode-nls'; import { CppBuildTaskProvider } from './cppBuildTaskProvider'; +import { HandleInsidersPrompt } from '../main'; nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })(); const localize: nls.LocalizeFunc = nls.loadMessageBundle(); @@ -290,11 +291,17 @@ export function updateLanguageConfigurations(): void { */ function onDidChangeSettings(event: vscode.ConfigurationChangeEvent): void { const activeClient: Client = clients.ActiveClient; + const changedActiveClientSettings: { [key: string]: string } = activeClient.onDidChangeSettings(event, true); clients.forEach(client => { if (client !== activeClient) { client.onDidChangeSettings(event, false); } }); + + const newUpdateChannel: string = changedActiveClientSettings['updateChannel']; + if (newUpdateChannel) { + HandleInsidersPrompt(); + } } export function onDidChangeActiveTextEditor(editor?: vscode.TextEditor): void { diff --git a/Extension/src/LanguageServer/settings.ts b/Extension/src/LanguageServer/settings.ts index e2029cba03..ec3f5eb6b1 100644 --- a/Extension/src/LanguageServer/settings.ts +++ b/Extension/src/LanguageServer/settings.ts @@ -211,6 +211,7 @@ export class CppSettings extends Settings { public get commentContinuationPatterns(): (string | CommentPattern)[] | undefined { return super.Section.get<(string | CommentPattern)[]>("commentContinuationPatterns"); } public get configurationWarnings(): string | undefined { return super.Section.get("configurationWarnings"); } public get preferredPathSeparator(): string | undefined { return super.Section.get("preferredPathSeparator"); } + public get updateChannel(): string | undefined { return super.Section.get("updateChannel"); } public get vcpkgEnabled(): boolean | undefined { return super.Section.get("vcpkg.enabled"); } public get addNodeAddonIncludePaths(): boolean | undefined { return super.Section.get("addNodeAddonIncludePaths"); } public get renameRequiresIdentifier(): boolean | undefined { return super.Section.get("renameRequiresIdentifier"); } diff --git a/Extension/src/main.ts b/Extension/src/main.ts index 383d840dd3..0f6e1e12cb 100644 --- a/Extension/src/main.ts +++ b/Extension/src/main.ts @@ -11,12 +11,17 @@ import * as path from 'path'; import * as Telemetry from './telemetry'; import * as util from './common'; import * as vscode from 'vscode'; +import * as nls from 'vscode-nls'; import { CppToolsApi, CppToolsExtension } from 'vscode-cpptools'; import { PlatformInformation } from './platform'; import { CppTools1 } from './cppTools1'; import { CppSettings } from './LanguageServer/settings'; import { PersistentState } from './LanguageServer/persistentState'; +import { TargetPopulation } from 'vscode-tas-client'; + +nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })(); +const localize: nls.LocalizeFunc = nls.loadMessageBundle(); const cppTools: CppTools1 = new CppTools1(); let languageServiceDisabled: boolean = false; @@ -49,12 +54,7 @@ export async function activate(context: vscode.ExtensionContext): Promise = new PersistentState("CPP.installedVersion", undefined); - if (!installedVersion.Value || installedVersion.Value !== util.packageJson.version) { - installedVersion.Value = util.packageJson.version; - sendTelemetry(info); - } + sendTelemetry(info); // Always attempt to make the binaries executable, not just when installedVersion changes. // The user may have uninstalled and reinstalled the same version. @@ -81,6 +81,9 @@ export async function activate(context: vscode.ExtensionContext): Promise = new PersistentState("CPP.displayedInsidersPrompt", false); + // Only display updateChannel deprecated message if updateChannel is set to "Insiders". + if (settings.updateChannel === "Insiders") { + if (!displayedInsidersPrompt.Value) { + displayedInsidersPrompt.Value = true; + const message: string = localize('updateChannel.changed', "The `C_Cpp.updateChannel` setting is deprecated. Do you want to enable install of pre-releases of the C/C++ extension via the Marketplace?"); + const yes: string = localize("yes.button", "Yes"); + const no: string = localize("no.button", "No"); + vscode.window.showInformationMessage(message, yes, no).then((selection) => { + switch (selection) { + case yes: + vscode.commands.executeCommand("workbench.extensions.installExtension", "ms-vscode.cpptools", { installPreReleaseVersion: true }); + break; + case no: + break; + default: + break; + } + }); + } + } else { + // Reset persistent value, so we prompt again they switch "Insiders" again. + if (displayedInsidersPrompt.Value) { + displayedInsidersPrompt.Value = false; + } + } + } +} From 40004aaf55d85ec0be76946e849eb26247ee5a42 Mon Sep 17 00:00:00 2001 From: Colen Garoutte-Carson Date: Mon, 10 Jan 2022 16:38:45 -0800 Subject: [PATCH 15/15] Avoid Insiders prompt if running VS Code Insiders --- Extension/src/common.ts | 9 +++++- Extension/src/main.ts | 62 +++++++++++++++++++++----------------- Extension/src/telemetry.ts | 2 +- 3 files changed, 43 insertions(+), 30 deletions(-) diff --git a/Extension/src/common.ts b/Extension/src/common.ts index 7058110320..bfd79d74e7 100644 --- a/Extension/src/common.ts +++ b/Extension/src/common.ts @@ -1238,7 +1238,7 @@ export function findPowerShell(): string | undefined { } } -export function getTargetPopulation(): TargetPopulation { +export function getCppToolsTargetPopulation(): TargetPopulation { // If insiders.flag is present, consider this an insiders build. // If release.flag is present, consider this a release build. // Otherwise, consider this an internal build. @@ -1249,3 +1249,10 @@ export function getTargetPopulation(): TargetPopulation { } return TargetPopulation.Internal; } + +export function isVsCodeInsiders(): Boolean { + return extensionPath.includes(".vscode-insiders") || + extensionPath.includes(".vscode-server-insiders") || + extensionPath.includes(".vscode-exploration") || + extensionPath.includes(".vscode-server-exploration"); +} diff --git a/Extension/src/main.ts b/Extension/src/main.ts index 0f6e1e12cb..26135f946d 100644 --- a/Extension/src/main.ts +++ b/Extension/src/main.ts @@ -135,34 +135,40 @@ function sendTelemetry(info: PlatformInformation): void { } export function HandleInsidersPrompt(): void { - const targetPopulation: TargetPopulation = util.getTargetPopulation(); - // Only display updateChannel deprecated message if not running an Insiders build. - if (targetPopulation === TargetPopulation.Public) { - const settings: CppSettings = new CppSettings(); - const displayedInsidersPrompt: PersistentState = new PersistentState("CPP.displayedInsidersPrompt", false); - // Only display updateChannel deprecated message if updateChannel is set to "Insiders". - if (settings.updateChannel === "Insiders") { - if (!displayedInsidersPrompt.Value) { - displayedInsidersPrompt.Value = true; - const message: string = localize('updateChannel.changed', "The `C_Cpp.updateChannel` setting is deprecated. Do you want to enable install of pre-releases of the C/C++ extension via the Marketplace?"); - const yes: string = localize("yes.button", "Yes"); - const no: string = localize("no.button", "No"); - vscode.window.showInformationMessage(message, yes, no).then((selection) => { - switch (selection) { - case yes: - vscode.commands.executeCommand("workbench.extensions.installExtension", "ms-vscode.cpptools", { installPreReleaseVersion: true }); - break; - case no: - break; - default: - break; - } - }); - } - } else { - // Reset persistent value, so we prompt again they switch "Insiders" again. - if (displayedInsidersPrompt.Value) { - displayedInsidersPrompt.Value = false; + // Only display this prompt to users who have updateChannel configured for Insiders, + // and who are not already configured to receive pre-release extensions. + + // Skip the prompt if using an Insiders build of VS Code, as it will default to using pre-release extensions. + if (!util.isVsCodeInsiders()) { + const targetPopulation: TargetPopulation = util.getCppToolsTargetPopulation(); + // Skip the prompt if already using an insiders build of cpptools. + if (targetPopulation === TargetPopulation.Public) { + const settings: CppSettings = new CppSettings(); + const displayedInsidersPrompt: PersistentState = new PersistentState("CPP.displayedInsidersPrompt", false); + // Skip the prompt if updateChannel was not set to Insiders. + if (settings.updateChannel === "Insiders") { + if (!displayedInsidersPrompt.Value) { + displayedInsidersPrompt.Value = true; + const message: string = localize('updateChannel.changed', "The `C_Cpp.updateChannel` setting is deprecated. Do you want to enable install of pre-releases of the C/C++ extension via the Marketplace?"); + const yes: string = localize("yes.button", "Yes"); + const no: string = localize("no.button", "No"); + vscode.window.showInformationMessage(message, yes, no).then((selection) => { + switch (selection) { + case yes: + vscode.commands.executeCommand("workbench.extensions.installExtension", "ms-vscode.cpptools", { installPreReleaseVersion: true }); + break; + case no: + break; + default: + break; + } + }); + } + } else { + // Reset persistent value, so we prompt again if they switch to "Insiders" again. + if (displayedInsidersPrompt.Value) { + displayedInsidersPrompt.Value = false; + } } } } diff --git a/Extension/src/telemetry.ts b/Extension/src/telemetry.ts index 36a4812471..1fbf033a13 100644 --- a/Extension/src/telemetry.ts +++ b/Extension/src/telemetry.ts @@ -62,7 +62,7 @@ export function activate(): void { if (util.extensionContext) { const packageInfo: IPackageInfo = getPackageInfo(); if (packageInfo) { - const targetPopulation: TargetPopulation = util.getTargetPopulation(); + const targetPopulation: TargetPopulation = util.getCppToolsTargetPopulation(); experimentationTelemetry = new ExperimentationTelemetry(new TelemetryReporter(packageInfo.name, packageInfo.version, appInsightsKey)); initializationPromise = getExperimentationServiceAsync(packageInfo.name, packageInfo.version, targetPopulation, experimentationTelemetry, util.extensionContext.globalState); }