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

Commit 78a842e

Browse files
paracyclevinistock
authored andcommitted
Make Ruby version detection fall through each version source
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.
1 parent 881e3ff commit 78a842e

File tree

4 files changed

+163
-40
lines changed

4 files changed

+163
-40
lines changed

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,7 @@
463463
"@types/glob": "^8.1.0",
464464
"@types/mocha": "^10.0.6",
465465
"@types/node": "20.x",
466+
"@types/sinon": "^17.0.3",
466467
"@types/vscode": "^1.68.0",
467468
"@typescript-eslint/eslint-plugin": "^5.62.0",
468469
"@typescript-eslint/parser": "^5.62.0",
@@ -476,6 +477,7 @@
476477
"mocha": "^10.2.0",
477478
"ovsx": "^0.8.3",
478479
"prettier": "^3.2.4",
480+
"sinon": "^17.0.1",
479481
"typescript": "^5.3.3",
480482
"vscode-oniguruma": "^2.0.1",
481483
"vscode-textmate": "^9.0.0"

src/ruby.ts

Lines changed: 21 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -209,22 +209,8 @@ export class Ruby implements RubyInterface {
209209
engine?: string;
210210
version: string;
211211
}> {
212-
let contents = await this.searchAndReadFile("dev.yml", false);
213-
if (contents) {
214-
const match = /- ruby: ('|")?(\d\.\d\.\d)/.exec(contents);
215-
const version = match && match[2];
216-
217-
if (!version) {
218-
throw new Error(
219-
"Found dev.yml file, but it did not define a Ruby version",
220-
);
221-
}
222-
223-
return { version };
224-
}
225-
226212
// Try to find a Ruby version in `.ruby-version`. We search parent directories until we find it or hit the root
227-
contents = await this.searchAndReadFile(".ruby-version", true);
213+
let contents = await this.searchAndReadFile(".ruby-version", true);
228214

229215
// rbenv allows setting a global Ruby version in `~/.rbenv/version`. If we couldn't find a project specific
230216
// `.ruby-version` file, then we need to check for the global one
@@ -239,13 +225,20 @@ export class Ruby implements RubyInterface {
239225
contents,
240226
);
241227

242-
if (!match || !match.groups) {
243-
throw new Error(
244-
"Found .ruby-version file, but it did not define a valid Ruby version",
245-
);
228+
if (match && match.groups) {
229+
return { engine: match.groups.engine, version: match.groups.version };
246230
}
231+
}
247232

248-
return { engine: match.groups.engine, version: match.groups.version };
233+
// Try to find a Ruby version in `dev.yml`. We search parent directories until we find it or hit the root
234+
contents = await this.searchAndReadFile("dev.yml", false);
235+
if (contents) {
236+
const match = /- ruby: ('|")?(\d\.\d\.\d)/.exec(contents);
237+
const version = match && match[2];
238+
239+
if (version) {
240+
return { version };
241+
}
249242
}
250243

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

257-
if (!version) {
258-
throw new Error(
259-
"Found .tool-versions file, but it did not define a Ruby version",
260-
);
250+
if (version) {
251+
return { version };
261252
}
262-
263-
return { version };
264253
}
265254

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

273-
if (!version) {
274-
throw new Error(
275-
"Found .rtx.toml file, but it did not define a Ruby version",
276-
);
262+
if (version) {
263+
return { version };
277264
}
278-
279-
return { version };
280265
}
281266

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

288-
if (!version) {
289-
throw new Error(
290-
"Found .mise.toml file, but it did not define a Ruby version",
291-
);
273+
if (version) {
274+
return { version };
292275
}
293-
294-
return { version };
295276
}
296277

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

src/test/suite/ruby.test.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,36 @@ suite("Ruby environment activation", () => {
3030
get: (_name: string) => undefined,
3131
update: (_name: string, _value: any) => Promise.resolve(),
3232
},
33+
globalState: {
34+
get: (_name: string) => undefined,
35+
update: (_name: string, _value: any) => Promise.resolve(),
36+
},
3337
} as unknown as vscode.ExtensionContext;
3438
const outputChannel = new WorkspaceChannel("fake", LOG_CHANNEL);
3539

40+
test("falls through all Ruby environment detection methods", async () => {
41+
const tmpPath = fs.mkdtempSync(path.join(os.tmpdir(), "ruby-lsp-test-"));
42+
const ruby = new Ruby(
43+
{
44+
uri: { fsPath: tmpPath },
45+
} as vscode.WorkspaceFolder,
46+
context,
47+
outputChannel,
48+
);
49+
fs.writeFileSync(path.join(tmpPath, "dev.yml"), "- ruby");
50+
fs.writeFileSync(path.join(tmpPath, ".ruby-version"), "");
51+
fs.writeFileSync(path.join(tmpPath, ".tool-versions"), "");
52+
fs.writeFileSync(path.join(tmpPath, ".rtx.toml"), "");
53+
fs.writeFileSync(
54+
path.join(tmpPath, ".mise.toml"),
55+
`[tools]
56+
ruby = '3.3.0'`,
57+
);
58+
59+
await ruby.activate();
60+
fs.rmSync(tmpPath, { recursive: true, force: true });
61+
});
62+
3663
test("fetches Ruby environment for .ruby-version", async () => {
3764
const tmpPath = fs.mkdtempSync(path.join(os.tmpdir(), "ruby-lsp-test-"));
3865
const ruby = new Ruby(
@@ -135,6 +162,23 @@ suite("Ruby environment activation", () => {
135162
fs.rmSync(tmpPath, { recursive: true, force: true });
136163
});
137164

165+
test("falls back to parsing Ruby environment from .ruby-version if dev.yml doesn't contain version", async () => {
166+
const tmpPath = fs.mkdtempSync(path.join(os.tmpdir(), "ruby-lsp-test-"));
167+
const ruby = new Ruby(
168+
{
169+
uri: { fsPath: tmpPath },
170+
} as vscode.WorkspaceFolder,
171+
context,
172+
outputChannel,
173+
);
174+
fs.writeFileSync(path.join(tmpPath, "dev.yml"), "- ruby");
175+
fs.writeFileSync(path.join(tmpPath, ".ruby-version"), "3.3.0");
176+
const rubyEnv = await ruby.activate();
177+
178+
assertRubyEnv(rubyEnv);
179+
fs.rmSync(tmpPath, { recursive: true, force: true });
180+
});
181+
138182
test("fetches Ruby environment for .tool-versions", async () => {
139183
const tmpPath = fs.mkdtempSync(path.join(os.tmpdir(), "ruby-lsp-test-"));
140184
const ruby = new Ruby(

yarn.lock

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,41 @@
506506
resolved "https://registry.yarnpkg.com/@shopify/prettier-config/-/prettier-config-1.1.2.tgz#612f87c0cd1196e8b43c85425e587d0fa7f1172d"
507507
integrity sha512-5ugCL9sPGzmOaZjeRGaWUWhHgAbemrS6z+R7v6gwiD+BiqSeoFhIY+imLpfdFCVpuOGalpHeCv6o3gv++EHs0A==
508508

509+
"@sinonjs/commons@^2.0.0":
510+
version "2.0.0"
511+
resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-2.0.0.tgz#fd4ca5b063554307e8327b4564bd56d3b73924a3"
512+
integrity sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==
513+
dependencies:
514+
type-detect "4.0.8"
515+
516+
"@sinonjs/commons@^3.0.0":
517+
version "3.0.1"
518+
resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.1.tgz#1029357e44ca901a615585f6d27738dbc89084cd"
519+
integrity sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==
520+
dependencies:
521+
type-detect "4.0.8"
522+
523+
"@sinonjs/fake-timers@^11.2.2":
524+
version "11.2.2"
525+
resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-11.2.2.tgz#50063cc3574f4a27bd8453180a04171c85cc9699"
526+
integrity sha512-G2piCSxQ7oWOxwGSAyFHfPIsyeJGXYtc6mFbnFA+kRXkiEnTl8c/8jul2S329iFBnDI9HGoeWWAZvuvOkZccgw==
527+
dependencies:
528+
"@sinonjs/commons" "^3.0.0"
529+
530+
"@sinonjs/samsam@^8.0.0":
531+
version "8.0.0"
532+
resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-8.0.0.tgz#0d488c91efb3fa1442e26abea81759dfc8b5ac60"
533+
integrity sha512-Bp8KUVlLp8ibJZrnvq2foVhP0IVX2CIprMJPK0vqGqgrDa0OHVKeZyBykqskkrdxV6yKBPmGasO8LVjAKR3Gew==
534+
dependencies:
535+
"@sinonjs/commons" "^2.0.0"
536+
lodash.get "^4.4.2"
537+
type-detect "^4.0.8"
538+
539+
"@sinonjs/text-encoding@^0.7.2":
540+
version "0.7.2"
541+
resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz#5981a8db18b56ba38ef0efb7d995b12aa7b51918"
542+
integrity sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==
543+
509544
"@tootallnate/once@1":
510545
version "1.1.2"
511546
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
@@ -551,6 +586,18 @@
551586
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.6.tgz#c65b2bfce1bec346582c07724e3f8c1017a20339"
552587
integrity sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==
553588

589+
"@types/sinon@^17.0.3":
590+
version "17.0.3"
591+
resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-17.0.3.tgz#9aa7e62f0a323b9ead177ed23a36ea757141a5fa"
592+
integrity sha512-j3uovdn8ewky9kRBG19bOwaZbexJu/XjtkHyjvUgt4xfPFz18dcORIMqnYh66Fx3Powhcr85NT5+er3+oViapw==
593+
dependencies:
594+
"@types/sinonjs__fake-timers" "*"
595+
596+
"@types/sinonjs__fake-timers@*":
597+
version "8.1.5"
598+
resolved "https://registry.yarnpkg.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.5.tgz#5fd3592ff10c1e9695d377020c033116cc2889f2"
599+
integrity sha512-mQkU2jY8jJEF7YHjHvsQO8+3ughTL1mcnn96igfhONmR+fUPSKIkefQYpSe8bsly2Ep7oQbn/6VG5/9/0qcArQ==
600+
554601
"@types/vscode@^1.68.0":
555602
version "1.85.0"
556603
resolved "https://registry.yarnpkg.com/@types/vscode/-/vscode-1.85.0.tgz#46beb07f0f626665b52d1e2294382b2bc63b602e"
@@ -1391,6 +1438,11 @@ [email protected]:
13911438
resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b"
13921439
integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==
13931440

1441+
diff@^5.1.0:
1442+
version "5.1.0"
1443+
resolved "https://registry.yarnpkg.com/diff/-/diff-5.1.0.tgz#bc52d298c5ea8df9194800224445ed43ffc87e40"
1444+
integrity sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==
1445+
13941446
dir-glob@^3.0.1:
13951447
version "3.0.1"
13961448
resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f"
@@ -2747,6 +2799,11 @@ jszip@^3.10.1:
27472799
readable-stream "~2.3.6"
27482800
setimmediate "^1.0.5"
27492801

2802+
just-extend@^6.2.0:
2803+
version "6.2.0"
2804+
resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-6.2.0.tgz#b816abfb3d67ee860482e7401564672558163947"
2805+
integrity sha512-cYofQu2Xpom82S6qD778jBDpwvvy39s1l/hrYij2u9AMdQcGRpaBu6kY4mVhuno5kJVi1DAz4aiphA2WI1/OAw==
2806+
27502807
keytar@^7.7.0:
27512808
version "7.9.0"
27522809
resolved "https://registry.yarnpkg.com/keytar/-/keytar-7.9.0.tgz#4c6225708f51b50cbf77c5aae81721964c2918cb"
@@ -2808,6 +2865,11 @@ locate-path@^6.0.0:
28082865
dependencies:
28092866
p-locate "^5.0.0"
28102867

2868+
lodash.get@^4.4.2:
2869+
version "4.4.2"
2870+
resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
2871+
integrity sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==
2872+
28112873
lodash.merge@^4.6.2:
28122874
version "4.6.2"
28132875
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
@@ -3013,6 +3075,17 @@ natural-compare@^1.4.0:
30133075
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
30143076
integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==
30153077

3078+
nise@^5.1.5:
3079+
version "5.1.7"
3080+
resolved "https://registry.yarnpkg.com/nise/-/nise-5.1.7.tgz#03ca96539efb306612eb60a8c5d6beeb208e27e5"
3081+
integrity sha512-wWtNUhkT7k58uvWTB/Gy26eA/EJKtPZFVAhEilN5UYVmmGRYOURbejRUyKm0Uu9XVEW7K5nBOZfR8VMB4QR2RQ==
3082+
dependencies:
3083+
"@sinonjs/commons" "^3.0.0"
3084+
"@sinonjs/fake-timers" "^11.2.2"
3085+
"@sinonjs/text-encoding" "^0.7.2"
3086+
just-extend "^6.2.0"
3087+
path-to-regexp "^6.2.1"
3088+
30163089
no-case@^3.0.4:
30173090
version "3.0.4"
30183091
resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d"
@@ -3309,6 +3382,11 @@ path-scurry@^1.10.1:
33093382
lru-cache "^9.1.1 || ^10.0.0"
33103383
minipass "^5.0.0 || ^6.0.2 || ^7.0.0"
33113384

3385+
path-to-regexp@^6.2.1:
3386+
version "6.2.1"
3387+
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.2.1.tgz#d54934d6798eb9e5ef14e7af7962c945906918e5"
3388+
integrity sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==
3389+
33123390
path-type@^4.0.0:
33133391
version "4.0.0"
33143392
resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
@@ -3699,6 +3777,18 @@ simple-get@^4.0.0:
36993777
once "^1.3.1"
37003778
simple-concat "^1.0.0"
37013779

3780+
sinon@^17.0.1:
3781+
version "17.0.1"
3782+
resolved "https://registry.yarnpkg.com/sinon/-/sinon-17.0.1.tgz#26b8ef719261bf8df43f925924cccc96748e407a"
3783+
integrity sha512-wmwE19Lie0MLT+ZYNpDymasPHUKTaZHUH/pKEubRXIzySv9Atnlw+BUMGCzWgV7b7wO+Hw6f1TEOr0IUnmU8/g==
3784+
dependencies:
3785+
"@sinonjs/commons" "^3.0.0"
3786+
"@sinonjs/fake-timers" "^11.2.2"
3787+
"@sinonjs/samsam" "^8.0.0"
3788+
diff "^5.1.0"
3789+
nise "^5.1.5"
3790+
supports-color "^7.2.0"
3791+
37023792
slash@^3.0.0:
37033793
version "3.0.0"
37043794
resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
@@ -3840,7 +3930,7 @@ supports-color@^5.3.0:
38403930
dependencies:
38413931
has-flag "^3.0.0"
38423932

3843-
supports-color@^7.1.0:
3933+
supports-color@^7.1.0, supports-color@^7.2.0:
38443934
version "7.2.0"
38453935
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
38463936
integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
@@ -3966,6 +4056,11 @@ type-check@^0.4.0, type-check@~0.4.0:
39664056
dependencies:
39674057
prelude-ls "^1.2.1"
39684058

4059+
[email protected], type-detect@^4.0.8:
4060+
version "4.0.8"
4061+
resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c"
4062+
integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==
4063+
39694064
type-fest@^0.20.2:
39704065
version "0.20.2"
39714066
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4"

0 commit comments

Comments
 (0)