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

Make Ruby version detection fall through each version source #1002

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
60 changes: 21 additions & 39 deletions src/ruby.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,22 +209,8 @@ export class Ruby implements RubyInterface {
engine?: string;
version: string;
}> {
let contents = await this.searchAndReadFile("dev.yml", false);
if (contents) {
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",
);
}

return { version };
}

// Try to find a Ruby version in `.ruby-version`. We search parent directories until we find it or hit the root
contents = await this.searchAndReadFile(".ruby-version", true);
let contents = await this.searchAndReadFile(".ruby-version", true);

// rbenv allows setting a global Ruby version in `~/.rbenv/version`. If we couldn't find a project specific
// `.ruby-version` file, then we need to check for the global one
Expand All @@ -239,13 +225,20 @@ 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 `dev.yml`. We search parent directories until we find it or hit the root
contents = await this.searchAndReadFile("dev.yml", false);
if (contents) {
const match = /- ruby: ('|")?(\d\.\d\.\d)/.exec(contents);
const version = match && match[2];

if (version) {
return { 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 +247,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 +259,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 +270,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
49 changes: 49 additions & 0 deletions src/test/suite/ruby.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import * as fs from "fs";
import * as path from "path";
import * as os from "os";

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

import { Ruby } from "../../ruby";
Expand Down Expand Up @@ -33,6 +34,37 @@ 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 " +
"`.ruby-version`, `.tool-versions`, `.rtx.toml` or `.mise.toml` files";
const mock = sinon.mock(ruby);
mock
.expects("showRubyFallbackDialog")
.withArgs(errorMessage)
.once()
.returns("3.2.2");

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 +167,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
Loading