update ls to 0.6.0and clangd to 13.0.0 (#738)

This commit is contained in:
Alberto Iannaccone 2022-01-24 17:21:19 +01:00 committed by GitHub
parent a71ac4c44d
commit 1d88263c85
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 148 additions and 106 deletions

View File

@ -155,6 +155,12 @@
}, },
"fwuploader": { "fwuploader": {
"version": "2.0.0" "version": "2.0.0"
},
"clangd": {
"version": "13.0.0"
},
"languageServer": {
"version": "0.6.0"
} }
} }
} }

View File

@ -4,13 +4,38 @@
// - https://downloads.arduino.cc/arduino-language-server/clangd/clangd_${VERSION}_${SUFFIX} // - 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 path = require('path');
const shell = require('shelljs'); const shell = require('shelljs');
const downloader = require('./downloader'); 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') const yargs = require('yargs')
.option('ls-version', { .option('ls-version', {
alias: 'lv', alias: 'lv',
@ -20,7 +45,7 @@
.option('clangd-version', { .option('clangd-version', {
alias: 'cv', alias: 'cv',
default: DEFAULT_CLANGD_VERSION, 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}.`, describe: `The version of 'clangd' to download. Defaults to ${DEFAULT_CLANGD_VERSION}.`,
}) })
.option('force-download', { .option('force-download', {
@ -35,32 +60,32 @@
const clangdVersion = yargs['clangd-version']; const clangdVersion = yargs['clangd-version'];
const force = yargs['force-download']; const force = yargs['force-download'];
const { platform, arch } = process; const { platform, arch } = process;
const platformArch = platform + '-' + arch;
const build = path.join(__dirname, '..', 'build'); const build = path.join(__dirname, '..', 'build');
const lsExecutablePath = path.join( const lsExecutablePath = path.join(
build, build,
`arduino-language-server${platform === 'win32' ? '.exe' : ''}` `arduino-language-server${platform === 'win32' ? '.exe' : ''}`
); );
let clangdExecutablePath, lsSuffix, clangdSuffix;
let clangdExecutablePath, lsSuffix, clangdPrefix; switch (platformArch) {
switch (platform) { case 'darwin-x64':
case 'darwin': clangdExecutablePath = path.join(build, 'clangd');
clangdExecutablePath = path.join(build, 'bin', 'clangd');
lsSuffix = 'macOS_64bit.tar.gz'; lsSuffix = 'macOS_64bit.tar.gz';
clangdPrefix = 'mac'; clangdSuffix = 'macOS_64bit';
break; break;
case 'linux': case 'linux-x64':
clangdExecutablePath = path.join(build, 'bin', 'clangd'); clangdExecutablePath = path.join(build, 'clangd');
lsSuffix = 'Linux_64bit.tar.gz'; lsSuffix = 'Linux_64bit.tar.gz';
clangdPrefix = 'linux'; clangdSuffix = 'Linux_64bit';
break; break;
case 'win32': case 'win32-x64':
clangdExecutablePath = path.join(build, 'bin', 'clangd.exe'); clangdExecutablePath = path.join(build, 'clangd.exe');
lsSuffix = 'Windows_64bit.zip'; lsSuffix = 'Windows_64bit.zip';
clangdPrefix = 'windows'; clangdSuffix = 'Windows_64bit';
break; break;
} }
if (!lsSuffix) { if (!lsSuffix || !clangdSuffix) {
shell.echo( shell.echo(
`The arduino-language-server is not available for ${platform} ${arch}.` `The arduino-language-server is not available for ${platform} ${arch}.`
); );
@ -74,7 +99,7 @@
}_${lsSuffix}`; }_${lsSuffix}`;
downloader.downloadUnzipAll(alsUrl, build, lsExecutablePath, force); 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, { downloader.downloadUnzipAll(clangdUrl, build, clangdExecutablePath, force, {
strip: 1, strip: 1,
}); // `strip`: the new clangd (12.x) is zipped into a folder, so we have to strip the outmost folder. }); // `strip`: the new clangd (12.x) is zipped into a folder, so we have to strip the outmost folder.

View File

@ -5,16 +5,17 @@ const download = require('download');
const decompress = require('decompress'); const decompress = require('decompress');
const unzip = require('decompress-unzip'); const unzip = require('decompress-unzip');
const untargz = require('decompress-targz'); const untargz = require('decompress-targz');
const untarbz2 = require('decompress-tarbz2');
process.on('unhandledRejection', (reason, _) => { process.on('unhandledRejection', (reason, _) => {
shell.echo(String(reason)); shell.echo(String(reason));
shell.exit(1); shell.exit(1);
throw reason; throw reason;
}); });
process.on('uncaughtException', error => { process.on('uncaughtException', (error) => {
shell.echo(String(error)); shell.echo(String(error));
shell.exit(1); shell.exit(1);
throw error; throw error;
}); });
/** /**
@ -23,55 +24,62 @@ process.on('uncaughtException', error => {
* @param filePrefix {string} Prefix of the file name found in the archive * @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. * @param force {boolean} Whether to download even if the target file exists. `false` by default.
*/ */
exports.downloadUnzipFile = async (url, targetFile, filePrefix, force = false) => { exports.downloadUnzipFile = async (
if (fs.existsSync(targetFile) && !force) { url,
shell.echo(`Skipping download because file already exists: ${targetFile}`); targetFile,
return; filePrefix,
} force = false
if (!fs.existsSync(path.dirname(targetFile))) { ) => {
if (shell.mkdir('-p', path.dirname(targetFile)).code !== 0) { if (fs.existsSync(targetFile) && !force) {
shell.echo('Could not create new directory.'); shell.echo(`Skipping download because file already exists: ${targetFile}`);
shell.exit(1); 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'); const downloads = path.join(__dirname, '..', 'downloads');
if (shell.rm('-rf', targetFile, downloads).code !== 0) { if (shell.rm('-rf', targetFile, downloads).code !== 0) {
shell.exit(1); shell.exit(1);
} }
shell.echo(`>>> Downloading from '${url}'...`); shell.echo(`>>> Downloading from '${url}'...`);
const data = await download(url); const data = await download(url);
shell.echo(`<<< Download succeeded.`); shell.echo(`<<< Download succeeded.`);
shell.echo('>>> Decompressing...'); shell.echo('>>> Decompressing...');
const files = await decompress(data, downloads, { const files = await decompress(data, downloads, {
plugins: [ plugins: [unzip(), untargz(), untarbz2()],
unzip(), });
untargz() if (files.length === 0) {
] shell.echo('Error ocurred while decompressing the archive.');
}); shell.exit(1);
if (files.length === 0) { }
shell.echo('Error ocurred while decompressing the archive.'); const fileIndex = files.findIndex((f) => f.path.startsWith(filePrefix));
shell.exit(1); if (fileIndex === -1) {
} shell.echo(
const fileIndex = files.findIndex(f => f.path.startsWith(filePrefix)); `The downloaded artifact does not contain any file with prefix ${filePrefix}.`
if (fileIndex === -1) { );
shell.echo(`The downloaded artifact does not contain any file with prefix ${filePrefix}.`); shell.exit(1);
shell.exit(1); }
} shell.echo('<<< Decompressing succeeded.');
shell.echo('<<< Decompressing succeeded.');
if (shell.mv('-f', path.join(downloads, files[fileIndex].path), targetFile).code !== 0) { if (
shell.echo(`Could not move file to target path: ${targetFile}`); shell.mv('-f', path.join(downloads, files[fileIndex].path), targetFile)
shell.exit(1); .code !== 0
} ) {
if (!fs.existsSync(targetFile)) { shell.echo(`Could not move file to target path: ${targetFile}`);
shell.echo(`Could not find file: ${targetFile}`); shell.exit(1);
shell.exit(1); }
} if (!fs.existsSync(targetFile)) {
shell.echo(`Done: ${targetFile}`); shell.echo(`Could not find file: ${targetFile}`);
} shell.exit(1);
}
shell.echo(`Done: ${targetFile}`);
};
/** /**
* @param url {string} Download URL * @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 targetFile {string} Path to the main file expected after decompressing
* @param force {boolean} Whether to download even if the target file exists * @param force {boolean} Whether to download even if the target file exists
*/ */
exports.downloadUnzipAll = async (url, targetDir, targetFile, force, decompressOptions = undefined) => { exports.downloadUnzipAll = async (
if (fs.existsSync(targetFile) && !force) { url,
shell.echo(`Skipping download because file already exists: ${targetFile}`); targetDir,
return; targetFile,
} force,
if (!fs.existsSync(targetDir)) { decompressOptions = undefined
if (shell.mkdir('-p', targetDir).code !== 0) { ) => {
shell.echo('Could not create new directory.'); if (fs.existsSync(targetFile) && !force) {
shell.exit(1); 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}'...`); shell.echo(`>>> Downloading from '${url}'...`);
const data = await download(url); const data = await download(url);
shell.echo(`<<< Download succeeded.`); shell.echo(`<<< Download succeeded.`);
shell.echo('>>> Decompressing...'); shell.echo('>>> Decompressing...');
let options = { let options = {
plugins: [ plugins: [unzip(), untargz(), untarbz2()],
unzip(), };
untargz() if (decompressOptions) {
] options = Object.assign(options, decompressOptions);
}; }
if (decompressOptions) { const files = await decompress(data, targetDir, options);
options = Object.assign(options, decompressOptions) if (files.length === 0) {
} shell.echo('Error ocurred while decompressing the archive.');
const files = await decompress(data, targetDir, options); shell.exit(1);
if (files.length === 0) { }
shell.echo('Error ocurred while decompressing the archive.'); shell.echo('<<< Decompressing succeeded.');
shell.exit(1);
}
shell.echo('<<< Decompressing succeeded.');
if (!fs.existsSync(targetFile)) { if (!fs.existsSync(targetFile)) {
shell.echo(`Could not find file: ${targetFile}`); shell.echo(`Could not find file: ${targetFile}`);
shell.exit(1); shell.exit(1);
} }
shell.echo(`Done: ${targetFile}`); shell.echo(`Done: ${targetFile}`);
} };

View File

@ -17,7 +17,7 @@ export class ExecutableServiceImpl implements ExecutableService {
}> { }> {
const [ls, clangd, cli, fwuploader] = await Promise.all([ const [ls, clangd, cli, fwuploader] = await Promise.all([
getExecPath('arduino-language-server', this.onError.bind(this)), 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-cli', this.onError.bind(this)),
getExecPath('arduino-fwuploader', this.onError.bind(this)), getExecPath('arduino-fwuploader', this.onError.bind(this)),
]); ]);

View File

@ -22,7 +22,7 @@ describe('getExecPath', () => {
}); });
it('should resolve clangd', async () => { 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'; const expected = os.platform() === 'win32' ? '\\clangd.exe' : '/clangd';
expect(actual).to.endsWith(expected); expect(actual).to.endsWith(expected);
}); });