From 1d88263c853cd9a431ff580227a9e5bb8edd64e5 Mon Sep 17 00:00:00 2001 From: Alberto Iannaccone Date: Mon, 24 Jan 2022 17:21:19 +0100 Subject: [PATCH] update ls to 0.6.0and clangd to 13.0.0 (#738) --- arduino-ide-extension/package.json | 6 + arduino-ide-extension/scripts/download-ls.js | 61 ++++-- arduino-ide-extension/scripts/downloader.js | 183 ++++++++++-------- .../src/node/executable-service-impl.ts | 2 +- .../src/test/node/exec-util.test.ts | 2 +- 5 files changed, 148 insertions(+), 106 deletions(-) diff --git a/arduino-ide-extension/package.json b/arduino-ide-extension/package.json index f1e56c4ea..ce092b8bc 100644 --- a/arduino-ide-extension/package.json +++ b/arduino-ide-extension/package.json @@ -155,6 +155,12 @@ }, "fwuploader": { "version": "2.0.0" + }, + "clangd": { + "version": "13.0.0" + }, + "languageServer": { + "version": "0.6.0" } } } diff --git a/arduino-ide-extension/scripts/download-ls.js b/arduino-ide-extension/scripts/download-ls.js index 2b65023b2..f00a8e625 100755 --- a/arduino-ide-extension/scripts/download-ls.js +++ b/arduino-ide-extension/scripts/download-ls.js @@ -4,13 +4,38 @@ // - https://downloads.arduino.cc/arduino-language-server/clangd/clangd_${VERSION}_${SUFFIX} (() => { - const DEFAULT_ALS_VERSION = '0.5.0'; - const DEFAULT_CLANGD_VERSION = 'snapshot_20210124'; - const path = require('path'); const shell = require('shelljs'); const downloader = require('./downloader'); + const [DEFAULT_ALS_VERSION, DEFAULT_CLANGD_VERSION] = (() => { + const pkg = require(path.join(__dirname, '..', 'package.json')); + if (!pkg) return undefined; + + const { arduino } = pkg; + if (!arduino) return undefined; + + const { languageServer, clangd } = arduino; + if (!languageServer) return undefined; + if (!clangd) return undefined; + + return [languageServer.version, clangd.version]; + })(); + + if (!DEFAULT_ALS_VERSION) { + shell.echo( + `Could not retrieve Arduino Language Server version info from the 'package.json'.` + ); + shell.exit(1); + } + + if (!DEFAULT_CLANGD_VERSION) { + shell.echo( + `Could not retrieve clangd version info from the 'package.json'.` + ); + shell.exit(1); + } + const yargs = require('yargs') .option('ls-version', { alias: 'lv', @@ -20,7 +45,7 @@ .option('clangd-version', { alias: 'cv', default: DEFAULT_CLANGD_VERSION, - choices: ['snapshot_20210124'], + choices: [DEFAULT_CLANGD_VERSION, 'snapshot_20210124'], describe: `The version of 'clangd' to download. Defaults to ${DEFAULT_CLANGD_VERSION}.`, }) .option('force-download', { @@ -35,32 +60,32 @@ const clangdVersion = yargs['clangd-version']; const force = yargs['force-download']; const { platform, arch } = process; - + const platformArch = platform + '-' + arch; const build = path.join(__dirname, '..', 'build'); const lsExecutablePath = path.join( build, `arduino-language-server${platform === 'win32' ? '.exe' : ''}` ); + let clangdExecutablePath, lsSuffix, clangdSuffix; - let clangdExecutablePath, lsSuffix, clangdPrefix; - switch (platform) { - case 'darwin': - clangdExecutablePath = path.join(build, 'bin', 'clangd'); + switch (platformArch) { + case 'darwin-x64': + clangdExecutablePath = path.join(build, 'clangd'); lsSuffix = 'macOS_64bit.tar.gz'; - clangdPrefix = 'mac'; + clangdSuffix = 'macOS_64bit'; break; - case 'linux': - clangdExecutablePath = path.join(build, 'bin', 'clangd'); + case 'linux-x64': + clangdExecutablePath = path.join(build, 'clangd'); lsSuffix = 'Linux_64bit.tar.gz'; - clangdPrefix = 'linux'; + clangdSuffix = 'Linux_64bit'; break; - case 'win32': - clangdExecutablePath = path.join(build, 'bin', 'clangd.exe'); + case 'win32-x64': + clangdExecutablePath = path.join(build, 'clangd.exe'); lsSuffix = 'Windows_64bit.zip'; - clangdPrefix = 'windows'; + clangdSuffix = 'Windows_64bit'; break; } - if (!lsSuffix) { + if (!lsSuffix || !clangdSuffix) { shell.echo( `The arduino-language-server is not available for ${platform} ${arch}.` ); @@ -74,7 +99,7 @@ }_${lsSuffix}`; downloader.downloadUnzipAll(alsUrl, build, lsExecutablePath, force); - const clangdUrl = `https://downloads.arduino.cc/arduino-language-server/clangd/clangd-${clangdPrefix}-${clangdVersion}.zip`; + const clangdUrl = `https://downloads.arduino.cc/tools/clangd_${clangdVersion}_${clangdSuffix}.tar.bz2`; downloader.downloadUnzipAll(clangdUrl, build, clangdExecutablePath, force, { strip: 1, }); // `strip`: the new clangd (12.x) is zipped into a folder, so we have to strip the outmost folder. diff --git a/arduino-ide-extension/scripts/downloader.js b/arduino-ide-extension/scripts/downloader.js index 6e81d480d..775aa0435 100644 --- a/arduino-ide-extension/scripts/downloader.js +++ b/arduino-ide-extension/scripts/downloader.js @@ -5,16 +5,17 @@ const download = require('download'); const decompress = require('decompress'); const unzip = require('decompress-unzip'); const untargz = require('decompress-targz'); +const untarbz2 = require('decompress-tarbz2'); process.on('unhandledRejection', (reason, _) => { - shell.echo(String(reason)); - shell.exit(1); - throw reason; + shell.echo(String(reason)); + shell.exit(1); + throw reason; }); -process.on('uncaughtException', error => { - shell.echo(String(error)); - shell.exit(1); - throw error; +process.on('uncaughtException', (error) => { + shell.echo(String(error)); + shell.exit(1); + throw error; }); /** @@ -23,55 +24,62 @@ process.on('uncaughtException', error => { * @param filePrefix {string} Prefix of the file name found in the archive * @param force {boolean} Whether to download even if the target file exists. `false` by default. */ -exports.downloadUnzipFile = async (url, targetFile, filePrefix, force = false) => { - if (fs.existsSync(targetFile) && !force) { - shell.echo(`Skipping download because file already exists: ${targetFile}`); - return; - } - if (!fs.existsSync(path.dirname(targetFile))) { - if (shell.mkdir('-p', path.dirname(targetFile)).code !== 0) { - shell.echo('Could not create new directory.'); - shell.exit(1); - } +exports.downloadUnzipFile = async ( + url, + targetFile, + filePrefix, + force = false +) => { + if (fs.existsSync(targetFile) && !force) { + shell.echo(`Skipping download because file already exists: ${targetFile}`); + return; + } + if (!fs.existsSync(path.dirname(targetFile))) { + if (shell.mkdir('-p', path.dirname(targetFile)).code !== 0) { + shell.echo('Could not create new directory.'); + shell.exit(1); } + } - const downloads = path.join(__dirname, '..', 'downloads'); - if (shell.rm('-rf', targetFile, downloads).code !== 0) { - shell.exit(1); - } + const downloads = path.join(__dirname, '..', 'downloads'); + if (shell.rm('-rf', targetFile, downloads).code !== 0) { + shell.exit(1); + } - shell.echo(`>>> Downloading from '${url}'...`); - const data = await download(url); - shell.echo(`<<< Download succeeded.`); + shell.echo(`>>> Downloading from '${url}'...`); + const data = await download(url); + shell.echo(`<<< Download succeeded.`); - shell.echo('>>> Decompressing...'); - const files = await decompress(data, downloads, { - plugins: [ - unzip(), - untargz() - ] - }); - if (files.length === 0) { - shell.echo('Error ocurred while decompressing the archive.'); - shell.exit(1); - } - const fileIndex = files.findIndex(f => f.path.startsWith(filePrefix)); - if (fileIndex === -1) { - shell.echo(`The downloaded artifact does not contain any file with prefix ${filePrefix}.`); - shell.exit(1); - } - shell.echo('<<< Decompressing succeeded.'); + shell.echo('>>> Decompressing...'); + const files = await decompress(data, downloads, { + plugins: [unzip(), untargz(), untarbz2()], + }); + if (files.length === 0) { + shell.echo('Error ocurred while decompressing the archive.'); + shell.exit(1); + } + const fileIndex = files.findIndex((f) => f.path.startsWith(filePrefix)); + if (fileIndex === -1) { + shell.echo( + `The downloaded artifact does not contain any file with prefix ${filePrefix}.` + ); + shell.exit(1); + } + shell.echo('<<< Decompressing succeeded.'); - if (shell.mv('-f', path.join(downloads, files[fileIndex].path), targetFile).code !== 0) { - shell.echo(`Could not move file to target path: ${targetFile}`); - shell.exit(1); - } - if (!fs.existsSync(targetFile)) { - shell.echo(`Could not find file: ${targetFile}`); - shell.exit(1); - } - shell.echo(`Done: ${targetFile}`); -} + if ( + shell.mv('-f', path.join(downloads, files[fileIndex].path), targetFile) + .code !== 0 + ) { + shell.echo(`Could not move file to target path: ${targetFile}`); + shell.exit(1); + } + if (!fs.existsSync(targetFile)) { + shell.echo(`Could not find file: ${targetFile}`); + shell.exit(1); + } + shell.echo(`Done: ${targetFile}`); +}; /** * @param url {string} Download URL @@ -79,42 +87,45 @@ exports.downloadUnzipFile = async (url, targetFile, filePrefix, force = false) = * @param targetFile {string} Path to the main file expected after decompressing * @param force {boolean} Whether to download even if the target file exists */ -exports.downloadUnzipAll = async (url, targetDir, targetFile, force, decompressOptions = undefined) => { - if (fs.existsSync(targetFile) && !force) { - shell.echo(`Skipping download because file already exists: ${targetFile}`); - return; - } - if (!fs.existsSync(targetDir)) { - if (shell.mkdir('-p', targetDir).code !== 0) { - shell.echo('Could not create new directory.'); - shell.exit(1); - } +exports.downloadUnzipAll = async ( + url, + targetDir, + targetFile, + force, + decompressOptions = undefined +) => { + if (fs.existsSync(targetFile) && !force) { + shell.echo(`Skipping download because file already exists: ${targetFile}`); + return; + } + if (!fs.existsSync(targetDir)) { + if (shell.mkdir('-p', targetDir).code !== 0) { + shell.echo('Could not create new directory.'); + shell.exit(1); } + } - shell.echo(`>>> Downloading from '${url}'...`); - const data = await download(url); - shell.echo(`<<< Download succeeded.`); + shell.echo(`>>> Downloading from '${url}'...`); + const data = await download(url); + shell.echo(`<<< Download succeeded.`); - shell.echo('>>> Decompressing...'); - let options = { - plugins: [ - unzip(), - untargz() - ] - }; - if (decompressOptions) { - options = Object.assign(options, decompressOptions) - } - const files = await decompress(data, targetDir, options); - if (files.length === 0) { - shell.echo('Error ocurred while decompressing the archive.'); - shell.exit(1); - } - shell.echo('<<< Decompressing succeeded.'); + shell.echo('>>> Decompressing...'); + let options = { + plugins: [unzip(), untargz(), untarbz2()], + }; + if (decompressOptions) { + options = Object.assign(options, decompressOptions); + } + const files = await decompress(data, targetDir, options); + if (files.length === 0) { + shell.echo('Error ocurred while decompressing the archive.'); + shell.exit(1); + } + shell.echo('<<< Decompressing succeeded.'); - if (!fs.existsSync(targetFile)) { - shell.echo(`Could not find file: ${targetFile}`); - shell.exit(1); - } - shell.echo(`Done: ${targetFile}`); -} + if (!fs.existsSync(targetFile)) { + shell.echo(`Could not find file: ${targetFile}`); + shell.exit(1); + } + shell.echo(`Done: ${targetFile}`); +}; diff --git a/arduino-ide-extension/src/node/executable-service-impl.ts b/arduino-ide-extension/src/node/executable-service-impl.ts index 8ebede450..0dbace0e3 100644 --- a/arduino-ide-extension/src/node/executable-service-impl.ts +++ b/arduino-ide-extension/src/node/executable-service-impl.ts @@ -17,7 +17,7 @@ export class ExecutableServiceImpl implements ExecutableService { }> { const [ls, clangd, cli, fwuploader] = await Promise.all([ getExecPath('arduino-language-server', this.onError.bind(this)), - getExecPath('clangd', this.onError.bind(this), undefined, true), + getExecPath('clangd', this.onError.bind(this), undefined), getExecPath('arduino-cli', this.onError.bind(this)), getExecPath('arduino-fwuploader', this.onError.bind(this)), ]); diff --git a/arduino-ide-extension/src/test/node/exec-util.test.ts b/arduino-ide-extension/src/test/node/exec-util.test.ts index b72c02018..ffbd1fbf6 100644 --- a/arduino-ide-extension/src/test/node/exec-util.test.ts +++ b/arduino-ide-extension/src/test/node/exec-util.test.ts @@ -22,7 +22,7 @@ describe('getExecPath', () => { }); it('should resolve clangd', async () => { - const actual = await getExecPath('clangd', onError, '--version', true); + const actual = await getExecPath('clangd', onError, '--version'); const expected = os.platform() === 'win32' ? '\\clangd.exe' : '/clangd'; expect(actual).to.endsWith(expected); });