diff --git a/Extension/.scripts/clean.ts b/Extension/.scripts/clean.ts index 92a85edab..0345fab8c 100644 --- a/Extension/.scripts/clean.ts +++ b/Extension/.scripts/clean.ts @@ -14,7 +14,7 @@ import { $root, Git, brightGreen, cyan, getModifiedIgnoredFiles, rimraf } from ' // list all untracked and ignored files that are modified/created: `git clean -Xd -n` export async function main() { - await rimraf(resolve($root, 'dist')); + await rimraf(resolve($root, 'dist'), resolve($root, 'LLVM')); } export async function all() { diff --git a/Extension/.scripts/copyExtensionBinaries.ts b/Extension/.scripts/copyExtensionBinaries.ts index 107f3a74c..aa97893ae 100644 --- a/Extension/.scripts/copyExtensionBinaries.ts +++ b/Extension/.scripts/copyExtensionBinaries.ts @@ -10,7 +10,7 @@ import { verbose } from '../src/Utility/Text/streams'; import { $args, $root, Git, green, heading, note, warn } from './common'; const extensionPrefix = 'ms-vscode.cpptools-'; -const foldersToCopy = ['bin', 'debugAdapters', 'LLVM'] as const; +const foldersToCopy = ['bin', 'debugAdapters'] as const; type InstalledExtension = { path: string; @@ -167,6 +167,14 @@ export async function main(sourcePath = $args[0]): Promise { await cp(source, destination, { recursive: true, force: true }); } + const legacyLLVMBin: string = join(installedExtensionPath, 'LLVM', 'bin'); + const legacyLLVMInfo = await stat(legacyLLVMBin).catch(() => undefined); + if (legacyLLVMInfo?.isDirectory()) { + console.log(`Copying ${green('LLVM/bin')} from ${legacyLLVMBin}`); + await cp(legacyLLVMBin, join($root, 'bin'), { recursive: true, force: true }); + } + await rm(join($root, 'LLVM'), { recursive: true, force: true }); + note(`Copied installed binaries into ${$root}`); await restoreTrackedFiles(); diff --git a/Extension/.scripts/vscode.test.mjs b/Extension/.scripts/vscode.test.mjs index 1feb17934..55725e8ec 100644 --- a/Extension/.scripts/vscode.test.mjs +++ b/Extension/.scripts/vscode.test.mjs @@ -1,6 +1,6 @@ import assert from 'node:assert/strict'; import { spawnSync } from 'node:child_process'; -import { mkdtempSync, rmSync } from 'node:fs'; +import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs'; import { createRequire } from 'node:module'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; @@ -40,6 +40,49 @@ function createInstaller() { return { ...installer, download, resolveCli, wait, mkdir, write, warn }; } +for (const clangToolsFolder of ['bin', join('LLVM', 'bin')]) { + test(`copies installed clang tools from ${clangToolsFolder} into bin`, async () => { + const testRoot = mkdtempSync(join(tmpdir(), 'cpptools-binary-copy-')); + const installedExtension = join(testRoot, 'vscode', 'extensions', 'ms-vscode.cpptools-1.2.3'); + const destination = join(testRoot, 'workspace'); + mkdirSync(join(installedExtension, 'bin'), { recursive: true }); + mkdirSync(join(installedExtension, 'debugAdapters'), { recursive: true }); + mkdirSync(join(installedExtension, clangToolsFolder), { recursive: true }); + writeFileSync(join(installedExtension, 'bin', 'cpptools'), 'cpptools'); + writeFileSync(join(installedExtension, 'debugAdapters', 'OpenDebugAD7'), 'debug adapter'); + writeFileSync(join(installedExtension, clangToolsFolder, 'clang-format'), 'clang-format'); + writeFileSync(join(installedExtension, clangToolsFolder, 'clang-tidy'), 'clang-tidy'); + mkdirSync(join(destination, 'LLVM', 'bin'), { recursive: true }); + writeFileSync(join(destination, 'LLVM', 'bin', 'stale-clang-format'), 'stale'); + + const Git = sinon.stub().resolves({ code: 0, stdio: { all: () => [] } }); + const copy = proxyquire(fileURLToPath(new URL('copyExtensionBinaries.ts', import.meta.url)), { + '../src/Utility/Text/streams': { verbose: sinon.stub() }, + 'node:os': { homedir: () => join(testRoot, 'home') }, + './common': { + $args: [], + $root: destination, + Git, + green: value => value, + heading: value => value, + note: sinon.stub(), + warn: sinon.stub() + } + }); + + try { + assert.equal(await copy.main(testRoot), '1.2.3'); + assert.equal(readFileSync(join(destination, 'bin', 'cpptools'), 'utf8'), 'cpptools'); + assert.equal(readFileSync(join(destination, 'bin', 'clang-format'), 'utf8'), 'clang-format'); + assert.equal(readFileSync(join(destination, 'bin', 'clang-tidy'), 'utf8'), 'clang-tidy'); + assert.equal(readFileSync(join(destination, 'debugAdapters', 'OpenDebugAD7'), 'utf8'), 'debug adapter'); + assert.equal(existsSync(join(destination, 'LLVM')), false); + } finally { + rmSync(testRoot, { recursive: true, force: true }); + } + }); +} + test('successful acquisition preserves the version, cache and CLI arguments without retries', async () => { const installer = createInstaller(); const result = await installer.install(); diff --git a/Extension/src/LanguageServer/settings.ts b/Extension/src/LanguageServer/settings.ts index 502144300..0978188ab 100644 --- a/Extension/src/LanguageServer/settings.ts +++ b/Extension/src/LanguageServer/settings.ts @@ -299,7 +299,7 @@ export class CppSettings extends Settings { // Attempt to invoke both our own version of clang-* to see if we can successfully execute it, and to get its version. let bundledVersion: string; try { - const bundledPath: string = getExtensionFilePath(`./LLVM/bin/${clangName}`); + const bundledPath: string = getExtensionFilePath(`./bin/${clangName}`); const output: string = execFileSync(bundledPath, ['--version']).toString(); bundledVersion = output.match(/(\d+\.\d+\.\d+)/)?.[1] ?? ""; if (!semver.valid(bundledVersion)) { diff --git a/Extension/src/main.ts b/Extension/src/main.ts index 45c1ef903..74c121c83 100644 --- a/Extension/src/main.ts +++ b/Extension/src/main.ts @@ -193,8 +193,8 @@ async function makeBinariesExecutable(): Promise { "./bin/cpptools-srv", "./bin/cpptools-srv2", "./bin/cpptools-wordexp", - "./LLVM/bin/clang-format", - "./LLVM/bin/clang-tidy", + "./bin/clang-format", + "./bin/clang-tidy", "./debugAdapters/bin/OpenDebugAD7" ]; commonBinaries.forEach(binary => promises.push(util.allowExecution(util.getExtensionFilePath(binary))));