Unnamed repository; edit this file 'description' to name the repository.
| -rw-r--r-- | editors/code/src/bootstrap.ts | 17 | ||||
| -rw-r--r-- | editors/code/tests/unit/bootstrap.test.ts | 71 |
2 files changed, 85 insertions, 3 deletions
diff --git a/editors/code/src/bootstrap.ts b/editors/code/src/bootstrap.ts index ca5b7e3ec7..440f21cbe3 100644 --- a/editors/code/src/bootstrap.ts +++ b/editors/code/src/bootstrap.ts @@ -176,14 +176,24 @@ async function fileExists(uri: vscode.Uri) { ); } +// Captures the elements of a `components` array. They are matched with `[^\]]` rather than `.` +// so that the array may be spread over several lines, which is just as valid TOML as keeping it +// on one, while still stopping at the end of the array. +const COMPONENTS_RE = /components\s*=\s*\[(?<components>[^\]]*)\]/; +// TOML strings come in both quote flavours. +const RA_COMPONENT_RE = /["']rust-analyzer["']/; + +function declaresRaComponent(toolchainFileContents: string): boolean { + const components = toolchainFileContents.match(COMPONENTS_RE)?.groups?.["components"]; + return components !== undefined && RA_COMPONENT_RE.test(components); +} + async function hasToolchainFileWithRaDeclared(uri: vscode.Uri): Promise<boolean> { try { const toolchainFileContents = new TextDecoder().decode( await vscode.workspace.fs.readFile(uri), ); - return ( - toolchainFileContents.match(/components\s*=\s*\[.*"rust-analyzer".*\]/g)?.length === 1 - ); + return declaresRaComponent(toolchainFileContents); } catch (_) { return false; } @@ -296,6 +306,7 @@ async function patchelf(dest: vscode.Uri): Promise<void> { } export const _private = { + declaresRaComponent, earliestToolchainPath, orderFromPath, }; diff --git a/editors/code/tests/unit/bootstrap.test.ts b/editors/code/tests/unit/bootstrap.test.ts index baabf4f897..259428da41 100644 --- a/editors/code/tests/unit/bootstrap.test.ts +++ b/editors/code/tests/unit/bootstrap.test.ts @@ -93,4 +93,75 @@ export async function getTests(ctx: Context) { ); }); }); + + await ctx.suite("Bootstrap/Detect RA component in toolchain file", (suite) => { + suite.addTest("Single line components array", async () => { + assert.ok( + _private.declaresRaComponent( + `[toolchain] +channel = "1.88" +components = ["cargo", "rust-analyzer", "rustfmt"] +`, + ), + ); + }); + + suite.addTest("Multi line components array", async () => { + assert.ok( + _private.declaresRaComponent( + `[toolchain] +channel = "1.88" +components = [ + "cargo", + "rust-analyzer", + "rustfmt", +] +profile = "default" +`, + ), + ); + }); + + suite.addTest("Components array with literal strings", async () => { + assert.ok(_private.declaresRaComponent(`components = ['cargo', 'rust-analyzer']`)); + }); + + suite.addTest("Components array without RA", async () => { + assert.ok( + !_private.declaresRaComponent( + `[toolchain] +channel = "1.88" +components = [ + "cargo", + "rustfmt", +] +`, + ), + ); + }); + + suite.addTest("No components array", async () => { + assert.ok( + !_private.declaresRaComponent( + `[toolchain] +channel = "1.88" +`, + ), + ); + }); + + suite.addTest("RA mentioned outside the components array", async () => { + assert.ok( + !_private.declaresRaComponent( + `[toolchain] +channel = "1.88" +components = [ + "cargo", +] +# add "rust-analyzer" here to use the matching server +`, + ), + ); + }); + }); } |