Skip to content

Commit 504d98e

Browse files
committed
Fix launcher file paths on Windows
1 parent 20c3979 commit 504d98e

File tree

7 files changed

+250
-108
lines changed

7 files changed

+250
-108
lines changed

exe/ruby-lsp

+4-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,10 @@ if ENV["BUNDLE_GEMFILE"].nil?
6464
# which gives us the opportunity to control which specs are activated and enter degraded mode if any gems failed to
6565
# install rather than failing to boot the server completely
6666
if options[:launcher]
67-
command = +"#{Gem.ruby} #{File.expand_path("ruby-lsp-launcher", __dir__)}"
67+
# Run `/path/to/ruby /path/to/exe/ruby-lsp-launcher` and ensuring that the Windows long format path is normalized
68+
# for exec
69+
command = +"#{Gem.ruby.delete_prefix("//?/")} "
70+
command << File.expand_path("ruby-lsp-launcher", __dir__).delete_prefix("//?/")
6871
command << " --debug" if options[:debug]
6972
exit exec(command)
7073
end

vscode/src/ruby.ts

+5-2
Original file line numberDiff line numberDiff line change
@@ -260,8 +260,11 @@ export class Ruby implements RubyInterface {
260260

261261
this.sanitizeEnvironment(env);
262262

263-
// We need to set the process environment too to make other extensions such as Sorbet find the right Ruby paths
264-
process.env = env;
263+
if (this.context.extensionMode !== vscode.ExtensionMode.Test) {
264+
// We need to set the process environment too to make other extensions such as Sorbet find the right Ruby paths
265+
process.env = env;
266+
}
267+
265268
this._env = env;
266269
this.rubyVersion = version;
267270
this.yjitEnabled = (yjit && major > 3) || (major === 3 && minor >= 2);

vscode/src/test/suite/client.test.ts

+11-82
Original file line numberDiff line numberDiff line change
@@ -31,41 +31,10 @@ import { after, afterEach, before } from "mocha";
3131
import { Ruby, ManagerIdentifier } from "../../ruby";
3232
import Client from "../../client";
3333
import { WorkspaceChannel } from "../../workspaceChannel";
34-
import { RUBY_VERSION, MAJOR, MINOR } from "../rubyVersion";
34+
import { MAJOR, MINOR } from "../rubyVersion";
3535

36-
import { FAKE_TELEMETRY } from "./fakeTelemetry";
37-
38-
class FakeLogger {
39-
receivedMessages = "";
40-
41-
trace(message: string, ..._args: any[]): void {
42-
this.receivedMessages += message;
43-
}
44-
45-
debug(message: string, ..._args: any[]): void {
46-
this.receivedMessages += message;
47-
}
48-
49-
info(message: string, ..._args: any[]): void {
50-
this.receivedMessages += message;
51-
}
52-
53-
warn(message: string, ..._args: any[]): void {
54-
this.receivedMessages += message;
55-
}
56-
57-
error(error: string | Error, ..._args: any[]): void {
58-
this.receivedMessages += error.toString();
59-
}
60-
61-
append(value: string): void {
62-
this.receivedMessages += value;
63-
}
64-
65-
appendLine(value: string): void {
66-
this.receivedMessages += value;
67-
}
68-
}
36+
import { FAKE_TELEMETRY, FakeLogger } from "./fakeTelemetry";
37+
import { createRubySymlinks } from "./helpers";
6938

7039
async function launchClient(workspaceUri: vscode.Uri) {
7140
const workspaceFolder: vscode.WorkspaceFolder = {
@@ -85,6 +54,8 @@ async function launchClient(workspaceUri: vscode.Uri) {
8554
const fakeLogger = new FakeLogger();
8655
const outputChannel = new WorkspaceChannel("fake", fakeLogger as any);
8756

57+
let managerConfig;
58+
8859
// Ensure that we're activating the correct Ruby version on CI
8960
if (process.env.CI) {
9061
await vscode.workspace
@@ -94,54 +65,12 @@ async function launchClient(workspaceUri: vscode.Uri) {
9465
.getConfiguration("rubyLsp")
9566
.update("linters", ["rubocop_internal"], true);
9667

97-
if (os.platform() === "linux") {
98-
await vscode.workspace
99-
.getConfiguration("rubyLsp")
100-
.update(
101-
"rubyVersionManager",
102-
{ identifier: ManagerIdentifier.Chruby },
103-
true,
104-
);
105-
106-
fs.mkdirSync(path.join(os.homedir(), ".rubies"), { recursive: true });
107-
fs.symlinkSync(
108-
`/opt/hostedtoolcache/Ruby/${RUBY_VERSION}/x64`,
109-
path.join(os.homedir(), ".rubies", RUBY_VERSION),
110-
);
111-
} else if (os.platform() === "darwin") {
112-
await vscode.workspace
113-
.getConfiguration("rubyLsp")
114-
.update(
115-
"rubyVersionManager",
116-
{ identifier: ManagerIdentifier.Chruby },
117-
true,
118-
);
119-
120-
fs.mkdirSync(path.join(os.homedir(), ".rubies"), { recursive: true });
121-
fs.symlinkSync(
122-
`/Users/runner/hostedtoolcache/Ruby/${RUBY_VERSION}/arm64`,
123-
path.join(os.homedir(), ".rubies", RUBY_VERSION),
124-
);
68+
createRubySymlinks();
69+
70+
if (os.platform() === "win32") {
71+
managerConfig = { identifier: ManagerIdentifier.RubyInstaller };
12572
} else {
126-
await vscode.workspace
127-
.getConfiguration("rubyLsp")
128-
.update(
129-
"rubyVersionManager",
130-
{ identifier: ManagerIdentifier.RubyInstaller },
131-
true,
132-
);
133-
134-
fs.symlinkSync(
135-
path.join(
136-
"C:",
137-
"hostedtoolcache",
138-
"windows",
139-
"Ruby",
140-
RUBY_VERSION,
141-
"x64",
142-
),
143-
path.join("C:", `Ruby${MAJOR}${MINOR}-${os.arch()}`),
144-
);
73+
managerConfig = { identifier: ManagerIdentifier.Chruby };
14574
}
14675
}
14776

@@ -151,7 +80,7 @@ async function launchClient(workspaceUri: vscode.Uri) {
15180
outputChannel,
15281
FAKE_TELEMETRY,
15382
);
154-
await ruby.activateRuby();
83+
await ruby.activateRuby(managerConfig);
15584
ruby.env.RUBY_LSP_BYPASS_TYPECHECKER = "true";
15685

15786
const virtualDocuments = new Map<string, string>();

vscode/src/test/suite/debugger.test.ts

+30-23
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import * as path from "path";
44
import * as os from "os";
55

66
import * as vscode from "vscode";
7-
import sinon from "sinon";
7+
import { afterEach, beforeEach } from "mocha";
88

99
import { Debugger } from "../../debugger";
1010
import { Ruby, ManagerIdentifier } from "../../ruby";
@@ -14,8 +14,25 @@ import { LOG_CHANNEL, asyncExec } from "../../common";
1414
import { RUBY_VERSION } from "../rubyVersion";
1515

1616
import { FAKE_TELEMETRY } from "./fakeTelemetry";
17+
import { createRubySymlinks } from "./helpers";
1718

1819
suite("Debugger", () => {
20+
const original = vscode.workspace
21+
.getConfiguration("debug")
22+
.get("saveBeforeStart");
23+
24+
beforeEach(async () => {
25+
await vscode.workspace
26+
.getConfiguration("debug")
27+
.update("saveBeforeStart", "none", true);
28+
});
29+
30+
afterEach(async () => {
31+
await vscode.workspace
32+
.getConfiguration("debug")
33+
.update("saveBeforeStart", original, true);
34+
});
35+
1936
test("Provide debug configurations returns the default configs", () => {
2037
const context = { subscriptions: [] } as unknown as vscode.ExtensionContext;
2138
const debug = new Debugger(context, () => {
@@ -161,26 +178,15 @@ suite("Debugger", () => {
161178
});
162179

163180
test("Launching the debugger", async () => {
164-
// eslint-disable-next-line no-process-env
165-
const manager = process.env.CI
166-
? ManagerIdentifier.None
167-
: ManagerIdentifier.Chruby;
181+
const manager =
182+
os.platform() === "win32"
183+
? { identifier: ManagerIdentifier.None }
184+
: { identifier: ManagerIdentifier.Chruby };
168185

169-
const configStub = sinon
170-
.stub(vscode.workspace, "getConfiguration")
171-
.returns({
172-
get: (name: string) => {
173-
if (name === "rubyVersionManager") {
174-
return { identifier: manager };
175-
} else if (name === "bundleGemfile") {
176-
return "";
177-
} else if (name === "saveBeforeStart") {
178-
return "none";
179-
}
180-
181-
return undefined;
182-
},
183-
} as unknown as vscode.WorkspaceConfiguration);
186+
// eslint-disable-next-line no-process-env
187+
if (process.env.CI) {
188+
createRubySymlinks();
189+
}
184190

185191
const tmpPath = fs.mkdtempSync(
186192
path.join(os.tmpdir(), "ruby-lsp-test-debugger"),
@@ -205,13 +211,14 @@ suite("Debugger", () => {
205211
name: path.basename(tmpPath),
206212
index: 0,
207213
};
214+
208215
const ruby = new Ruby(
209216
context,
210217
workspaceFolder,
211218
outputChannel,
212219
FAKE_TELEMETRY,
213220
);
214-
await ruby.activateRuby();
221+
await ruby.activateRuby(manager);
215222

216223
try {
217224
await asyncExec("bundle install", { env: ruby.env, cwd: tmpPath });
@@ -247,11 +254,11 @@ suite("Debugger", () => {
247254
// the termination callback or else we try to dispose of the debugger client too early, but we need to wait for that
248255
// so that we can clean up stubs otherwise they leak into other tests.
249256
await new Promise<void>((resolve) => {
250-
vscode.debug.onDidTerminateDebugSession((_session) => {
251-
configStub.restore();
257+
const callback = vscode.debug.onDidTerminateDebugSession((_session) => {
252258
debug.dispose();
253259
context.subscriptions.forEach((subscription) => subscription.dispose());
254260
fs.rmSync(tmpPath, { recursive: true, force: true });
261+
callback.dispose();
255262
resolve();
256263
});
257264
});

vscode/src/test/suite/fakeTelemetry.ts

+32
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,35 @@ export const FAKE_TELEMETRY = vscode.env.createTelemetryLogger(
2727
ignoreUnhandledErrors: true,
2828
},
2929
);
30+
31+
export class FakeLogger {
32+
receivedMessages = "";
33+
34+
trace(message: string, ..._args: any[]): void {
35+
this.receivedMessages += message;
36+
}
37+
38+
debug(message: string, ..._args: any[]): void {
39+
this.receivedMessages += message;
40+
}
41+
42+
info(message: string, ..._args: any[]): void {
43+
this.receivedMessages += message;
44+
}
45+
46+
warn(message: string, ..._args: any[]): void {
47+
this.receivedMessages += message;
48+
}
49+
50+
error(error: string | Error, ..._args: any[]): void {
51+
this.receivedMessages += error.toString();
52+
}
53+
54+
append(value: string): void {
55+
this.receivedMessages += value;
56+
}
57+
58+
appendLine(value: string): void {
59+
this.receivedMessages += value;
60+
}
61+
}

vscode/src/test/suite/helpers.ts

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/* eslint-disable no-process-env */
2+
import path from "path";
3+
import os from "os";
4+
import fs from "fs";
5+
6+
import { MAJOR, MINOR, RUBY_VERSION } from "../rubyVersion";
7+
8+
export function createRubySymlinks() {
9+
if (os.platform() === "linux") {
10+
const linkPath = path.join(os.homedir(), ".rubies", RUBY_VERSION);
11+
12+
if (!fs.existsSync(linkPath)) {
13+
fs.mkdirSync(path.join(os.homedir(), ".rubies"), { recursive: true });
14+
fs.symlinkSync(`/opt/hostedtoolcache/Ruby/${RUBY_VERSION}/x64`, linkPath);
15+
}
16+
} else if (os.platform() === "darwin") {
17+
const linkPath = path.join(os.homedir(), ".rubies", RUBY_VERSION);
18+
19+
if (!fs.existsSync(linkPath)) {
20+
fs.mkdirSync(path.join(os.homedir(), ".rubies"), { recursive: true });
21+
fs.symlinkSync(
22+
`/Users/runner/hostedtoolcache/Ruby/${RUBY_VERSION}/arm64`,
23+
linkPath,
24+
);
25+
}
26+
} else {
27+
const linkPath = path.join("C:", `Ruby${MAJOR}${MINOR}-${os.arch()}`);
28+
29+
if (!fs.existsSync(linkPath)) {
30+
fs.symlinkSync(
31+
path.join(
32+
"C:",
33+
"hostedtoolcache",
34+
"windows",
35+
"Ruby",
36+
RUBY_VERSION,
37+
"x64",
38+
),
39+
linkPath,
40+
);
41+
}
42+
}
43+
}

0 commit comments

Comments
 (0)