Skip to content
This repository has been archived by the owner on May 30, 2024. It is now read-only.

Commit

Permalink
Make Ruby version detection fall through each version source
Browse files Browse the repository at this point in the history
Currently Ruby version detection fails early when it is able to find a particular kind of Ruby version file, but is unable to extract a valid Ruby version from the file. This commit makes it so that Ruby version detection falls through each version source until it finds a valid Ruby version, or fails with a message that no valid Ruby version could be found.
  • Loading branch information
paracycle committed Jan 25, 2024
1 parent 456f287 commit e06ed2b
Show file tree
Hide file tree
Showing 4 changed files with 157 additions and 33 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,7 @@
"@types/glob": "^8.1.0",
"@types/mocha": "^10.0.6",
"@types/node": "20.x",
"@types/sinon": "^17.0.3",
"@types/vscode": "^1.68.0",
"@typescript-eslint/eslint-plugin": "^5.62.0",
"@typescript-eslint/parser": "^5.62.0",
Expand All @@ -476,6 +477,7 @@
"mocha": "^10.2.0",
"ovsx": "^0.8.3",
"prettier": "^3.2.2",
"sinon": "^17.0.1",
"typescript": "^5.3.3",
"vscode-oniguruma": "^2.0.1",
"vscode-textmate": "^9.0.0"
Expand Down
43 changes: 12 additions & 31 deletions src/ruby.ts
Original file line number Diff line number Diff line change
Expand Up @@ -214,13 +214,9 @@ export class Ruby implements RubyInterface {
const match = /- ruby: ('|")?(\d\.\d\.\d)/.exec(contents);
const version = match && match[2];

if (!version) {
throw new Error(
"Found dev.yml file, but it did not define a Ruby version",
);
if (version) {
return { version };
}

return { version };
}

// Try to find a Ruby version in `.ruby-version`. We search parent directories until we find it or hit the root
Expand All @@ -239,13 +235,9 @@ export class Ruby implements RubyInterface {
contents,
);

if (!match || !match.groups) {
throw new Error(
"Found .ruby-version file, but it did not define a valid Ruby version",
);
if (match && match.groups) {
return { engine: match.groups.engine, version: match.groups.version };
}

return { engine: match.groups.engine, version: match.groups.version };
}

// Try to find a Ruby version in `.tool-versions`. We search parent directories until we find it or hit the root
Expand All @@ -254,13 +246,9 @@ export class Ruby implements RubyInterface {
const match = /ruby (\d\.\d\.\d(-[A-Za-z0-9]+)?)/.exec(contents);
const version = match && match[1];

if (!version) {
throw new Error(
"Found .tool-versions file, but it did not define a Ruby version",
);
if (version) {
return { version };
}

return { version };
}

// Try to find a Ruby version in `.rtx.toml`. Note: rtx has been renamed to mise, which is handled below. We will
Expand All @@ -270,13 +258,9 @@ export class Ruby implements RubyInterface {
const match = /ruby\s+=\s+("|')(.*)("|')/.exec(contents);
const version = match && match[2];

if (!version) {
throw new Error(
"Found .rtx.toml file, but it did not define a Ruby version",
);
if (version) {
return { version };
}

return { version };
}

// Try to find a Ruby version in `.mise.toml`
Expand All @@ -285,17 +269,14 @@ export class Ruby implements RubyInterface {
const match = /ruby\s+=\s+("|')(.*)("|')/.exec(contents);
const version = match && match[2];

if (!version) {
throw new Error(
"Found .mise.toml file, but it did not define a Ruby version",
);
if (version) {
return { version };
}

return { version };
}

throw new Error(
"Could not find a configured Ruby version. Searched for .ruby-version and .tools-versions",
"Could not find a valid Ruby version in any of `.ruby-version`, `.tool-versions`, `.rtx.toml` " +
"or `.mise.toml` files",
);
}

Expand Down
48 changes: 47 additions & 1 deletion src/test/suite/ruby.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as assert from "assert";
import * as fs from "fs";
import * as path from "path";
import * as os from "os";

Check failure on line 4 in src/test/suite/ruby.test.ts

View workflow job for this annotation

GitHub Actions / lint

There should be at least one empty line between import groups

Check failure on line 4 in src/test/suite/ruby.test.ts

View workflow job for this annotation

GitHub Actions / lint

There should be at least one empty line between import groups

import * as sinon from "sinon";
import * as vscode from "vscode";

import { Ruby } from "../../ruby";
Expand Down Expand Up @@ -33,6 +33,35 @@ suite("Ruby environment activation", () => {
} as unknown as vscode.ExtensionContext;
const outputChannel = new WorkspaceChannel("fake", LOG_CHANNEL);

test("falls through all Ruby environment detection methods", async () => {
const tmpPath = fs.mkdtempSync(path.join(os.tmpdir(), "ruby-lsp-test-"));
const ruby = new Ruby(
{
uri: { fsPath: tmpPath },
} as vscode.WorkspaceFolder,
context,
outputChannel,
);
fs.writeFileSync(path.join(tmpPath, "dev.yml"), "- ruby");
fs.writeFileSync(path.join(tmpPath, ".ruby-version"), "");
fs.writeFileSync(path.join(tmpPath, ".tool-versions"), "");
fs.writeFileSync(path.join(tmpPath, ".rtx.toml"), "");
fs.writeFileSync(path.join(tmpPath, ".mise.toml"), "");

const errorMessage = "Could not find a valid Ruby version in any of " +

Check failure on line 51 in src/test/suite/ruby.test.ts

View workflow job for this annotation

GitHub Actions / lint

Insert `⏎·····`

Check failure on line 51 in src/test/suite/ruby.test.ts

View workflow job for this annotation

GitHub Actions / lint

Insert `⏎·····`
"`.ruby-version`, `.tool-versions`, `.rtx.toml` or `.mise.toml` files";

Check failure on line 52 in src/test/suite/ruby.test.ts

View workflow job for this annotation

GitHub Actions / lint

Delete `··`

Check failure on line 52 in src/test/suite/ruby.test.ts

View workflow job for this annotation

GitHub Actions / lint

Delete `··`
const mock = sinon.mock(ruby);
mock.expects("showRubyFallbackDialog")

Check failure on line 54 in src/test/suite/ruby.test.ts

View workflow job for this annotation

GitHub Actions / lint

Insert `⏎······`

Check failure on line 54 in src/test/suite/ruby.test.ts

View workflow job for this annotation

GitHub Actions / lint

Insert `⏎······`
.withArgs(errorMessage)

Check failure on line 55 in src/test/suite/ruby.test.ts

View workflow job for this annotation

GitHub Actions / lint

Replace `········` with `······`

Check failure on line 55 in src/test/suite/ruby.test.ts

View workflow job for this annotation

GitHub Actions / lint

Replace `········` with `······`
.once()

Check failure on line 56 in src/test/suite/ruby.test.ts

View workflow job for this annotation

GitHub Actions / lint

Delete `··`

Check failure on line 56 in src/test/suite/ruby.test.ts

View workflow job for this annotation

GitHub Actions / lint

Delete `··`
.returns("3.2.2");

Check failure on line 57 in src/test/suite/ruby.test.ts

View workflow job for this annotation

GitHub Actions / lint

Delete `··`

Check failure on line 57 in src/test/suite/ruby.test.ts

View workflow job for this annotation

GitHub Actions / lint

Delete `··`

await ruby.activate();

mock.verify();
fs.rmSync(tmpPath, { recursive: true, force: true });
});

test("fetches Ruby environment for .ruby-version", async () => {
const tmpPath = fs.mkdtempSync(path.join(os.tmpdir(), "ruby-lsp-test-"));
const ruby = new Ruby(
Expand Down Expand Up @@ -135,6 +164,23 @@ suite("Ruby environment activation", () => {
fs.rmSync(tmpPath, { recursive: true, force: true });
});

test("falls back to parsing Ruby environment from .ruby-version if dev.yml doesn't contain version", async () => {
const tmpPath = fs.mkdtempSync(path.join(os.tmpdir(), "ruby-lsp-test-"));
const ruby = new Ruby(
{
uri: { fsPath: tmpPath },
} as vscode.WorkspaceFolder,
context,
outputChannel,
);
fs.writeFileSync(path.join(tmpPath, "dev.yml"), "- ruby");
fs.writeFileSync(path.join(tmpPath, ".ruby-version"), "3.2.2");
const rubyEnv = await ruby.activate();

assertRubyEnv(rubyEnv);
fs.rmSync(tmpPath, { recursive: true, force: true });
});

test("fetches Ruby environment for .tool-versions", async () => {
const tmpPath = fs.mkdtempSync(path.join(os.tmpdir(), "ruby-lsp-test-"));
const ruby = new Ruby(
Expand Down
97 changes: 96 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,41 @@
resolved "https://registry.yarnpkg.com/@shopify/prettier-config/-/prettier-config-1.1.2.tgz#612f87c0cd1196e8b43c85425e587d0fa7f1172d"
integrity sha512-5ugCL9sPGzmOaZjeRGaWUWhHgAbemrS6z+R7v6gwiD+BiqSeoFhIY+imLpfdFCVpuOGalpHeCv6o3gv++EHs0A==

"@sinonjs/commons@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-2.0.0.tgz#fd4ca5b063554307e8327b4564bd56d3b73924a3"
integrity sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==
dependencies:
type-detect "4.0.8"

"@sinonjs/commons@^3.0.0":
version "3.0.1"
resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.1.tgz#1029357e44ca901a615585f6d27738dbc89084cd"
integrity sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==
dependencies:
type-detect "4.0.8"

"@sinonjs/fake-timers@^11.2.2":
version "11.2.2"
resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-11.2.2.tgz#50063cc3574f4a27bd8453180a04171c85cc9699"
integrity sha512-G2piCSxQ7oWOxwGSAyFHfPIsyeJGXYtc6mFbnFA+kRXkiEnTl8c/8jul2S329iFBnDI9HGoeWWAZvuvOkZccgw==
dependencies:
"@sinonjs/commons" "^3.0.0"

"@sinonjs/samsam@^8.0.0":
version "8.0.0"
resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-8.0.0.tgz#0d488c91efb3fa1442e26abea81759dfc8b5ac60"
integrity sha512-Bp8KUVlLp8ibJZrnvq2foVhP0IVX2CIprMJPK0vqGqgrDa0OHVKeZyBykqskkrdxV6yKBPmGasO8LVjAKR3Gew==
dependencies:
"@sinonjs/commons" "^2.0.0"
lodash.get "^4.4.2"
type-detect "^4.0.8"

"@sinonjs/text-encoding@^0.7.2":
version "0.7.2"
resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz#5981a8db18b56ba38ef0efb7d995b12aa7b51918"
integrity sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==

"@tootallnate/once@1":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
Expand Down Expand Up @@ -551,6 +586,18 @@
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.6.tgz#c65b2bfce1bec346582c07724e3f8c1017a20339"
integrity sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==

"@types/sinon@^17.0.3":
version "17.0.3"
resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-17.0.3.tgz#9aa7e62f0a323b9ead177ed23a36ea757141a5fa"
integrity sha512-j3uovdn8ewky9kRBG19bOwaZbexJu/XjtkHyjvUgt4xfPFz18dcORIMqnYh66Fx3Powhcr85NT5+er3+oViapw==
dependencies:
"@types/sinonjs__fake-timers" "*"

"@types/sinonjs__fake-timers@*":
version "8.1.5"
resolved "https://registry.yarnpkg.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.5.tgz#5fd3592ff10c1e9695d377020c033116cc2889f2"
integrity sha512-mQkU2jY8jJEF7YHjHvsQO8+3ughTL1mcnn96igfhONmR+fUPSKIkefQYpSe8bsly2Ep7oQbn/6VG5/9/0qcArQ==

"@types/vscode@^1.68.0":
version "1.85.0"
resolved "https://registry.yarnpkg.com/@types/vscode/-/vscode-1.85.0.tgz#46beb07f0f626665b52d1e2294382b2bc63b602e"
Expand Down Expand Up @@ -1390,6 +1437,11 @@ diff@5.0.0:
resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b"
integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==

diff@^5.1.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/diff/-/diff-5.1.0.tgz#bc52d298c5ea8df9194800224445ed43ffc87e40"
integrity sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==

dir-glob@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f"
Expand Down Expand Up @@ -2739,6 +2791,11 @@ jszip@^3.10.1:
readable-stream "~2.3.6"
setimmediate "^1.0.5"

just-extend@^6.2.0:
version "6.2.0"
resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-6.2.0.tgz#b816abfb3d67ee860482e7401564672558163947"
integrity sha512-cYofQu2Xpom82S6qD778jBDpwvvy39s1l/hrYij2u9AMdQcGRpaBu6kY4mVhuno5kJVi1DAz4aiphA2WI1/OAw==

keytar@^7.7.0:
version "7.9.0"
resolved "https://registry.yarnpkg.com/keytar/-/keytar-7.9.0.tgz#4c6225708f51b50cbf77c5aae81721964c2918cb"
Expand Down Expand Up @@ -2800,6 +2857,11 @@ locate-path@^6.0.0:
dependencies:
p-locate "^5.0.0"

lodash.get@^4.4.2:
version "4.4.2"
resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
integrity sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==

lodash.merge@^4.6.2:
version "4.6.2"
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
Expand Down Expand Up @@ -3005,6 +3067,17 @@ natural-compare@^1.4.0:
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==

nise@^5.1.5:
version "5.1.7"
resolved "https://registry.yarnpkg.com/nise/-/nise-5.1.7.tgz#03ca96539efb306612eb60a8c5d6beeb208e27e5"
integrity sha512-wWtNUhkT7k58uvWTB/Gy26eA/EJKtPZFVAhEilN5UYVmmGRYOURbejRUyKm0Uu9XVEW7K5nBOZfR8VMB4QR2RQ==
dependencies:
"@sinonjs/commons" "^3.0.0"
"@sinonjs/fake-timers" "^11.2.2"
"@sinonjs/text-encoding" "^0.7.2"
just-extend "^6.2.0"
path-to-regexp "^6.2.1"

no-case@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d"
Expand Down Expand Up @@ -3301,6 +3374,11 @@ path-scurry@^1.10.1:
lru-cache "^9.1.1 || ^10.0.0"
minipass "^5.0.0 || ^6.0.2 || ^7.0.0"

path-to-regexp@^6.2.1:
version "6.2.1"
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.2.1.tgz#d54934d6798eb9e5ef14e7af7962c945906918e5"
integrity sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==

path-type@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
Expand Down Expand Up @@ -3691,6 +3769,18 @@ simple-get@^4.0.0:
once "^1.3.1"
simple-concat "^1.0.0"

sinon@^17.0.1:
version "17.0.1"
resolved "https://registry.yarnpkg.com/sinon/-/sinon-17.0.1.tgz#26b8ef719261bf8df43f925924cccc96748e407a"
integrity sha512-wmwE19Lie0MLT+ZYNpDymasPHUKTaZHUH/pKEubRXIzySv9Atnlw+BUMGCzWgV7b7wO+Hw6f1TEOr0IUnmU8/g==
dependencies:
"@sinonjs/commons" "^3.0.0"
"@sinonjs/fake-timers" "^11.2.2"
"@sinonjs/samsam" "^8.0.0"
diff "^5.1.0"
nise "^5.1.5"
supports-color "^7.2.0"

slash@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
Expand Down Expand Up @@ -3832,7 +3922,7 @@ supports-color@^5.3.0:
dependencies:
has-flag "^3.0.0"

supports-color@^7.1.0:
supports-color@^7.1.0, supports-color@^7.2.0:
version "7.2.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
Expand Down Expand Up @@ -3958,6 +4048,11 @@ type-check@^0.4.0, type-check@~0.4.0:
dependencies:
prelude-ls "^1.2.1"

type-detect@4.0.8, type-detect@^4.0.8:
version "4.0.8"
resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c"
integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==

type-fest@^0.20.2:
version "0.20.2"
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4"
Expand Down

0 comments on commit e06ed2b

Please sign in to comment.