diff --git a/vscode/src/ruby.ts b/vscode/src/ruby.ts index 2fae0b124..24278f278 100644 --- a/vscode/src/ruby.ts +++ b/vscode/src/ruby.ts @@ -150,7 +150,6 @@ export class Ruby implements RubyInterface { } this.fetchRubyVersionInfo(); - this.deleteGcEnvironmentVariables(); await this.setupBundlePath(); this._error = false; } catch (error: any) { @@ -172,6 +171,8 @@ export class Ruby implements RubyInterface { const { env, version, yjit } = await manager.activate(); const [major, minor, _patch] = version.split(".").map(Number); + this.sanitizeEnvironment(env); + // We need to set the process environment too to make other extensions such as Sorbet find the right Ruby paths process.env = env; this._env = env; @@ -240,12 +241,20 @@ export class Ruby implements RubyInterface { } } - private deleteGcEnvironmentVariables() { - Object.keys(this._env).forEach((key) => { + // Deletes environment variables that are known to cause issues for launching the Ruby LSP. For example, GC tuning + // variables or verbose settings + private sanitizeEnvironment(env: NodeJS.ProcessEnv) { + // Delete all GC tuning variables + Object.keys(env).forEach((key) => { if (key.startsWith("RUBY_GC")) { - delete this._env[key]; + delete env[key]; } }); + + // Delete verbose or debug related settings. These often make Bundler or other dependencies print things to STDOUT, + // which breaks the client/server communication + delete env.VERBOSE; + delete env.DEBUG; } private async setupBundlePath() { diff --git a/vscode/src/test/suite/ruby.test.ts b/vscode/src/test/suite/ruby.test.ts index c7d1a136c..57c73d0f3 100644 --- a/vscode/src/test/suite/ruby.test.ts +++ b/vscode/src/test/suite/ruby.test.ts @@ -1,3 +1,4 @@ +/* eslint-disable no-process-env */ import * as assert from "assert"; import * as path from "path"; @@ -9,10 +10,16 @@ import { WorkspaceChannel } from "../../workspaceChannel"; import { LOG_CHANNEL } from "../../common"; suite("Ruby environment activation", () => { - let ruby: Ruby; + const workspacePath = path.dirname( + path.dirname(path.dirname(path.dirname(__dirname))), + ); + const workspaceFolder: vscode.WorkspaceFolder = { + uri: vscode.Uri.file(workspacePath), + name: path.basename(workspacePath), + index: 0, + }; test("Activate fetches Ruby information when outside of Ruby LSP", async () => { - // eslint-disable-next-line no-process-env const manager = process.env.CI ? ManagerIdentifier.None : ManagerIdentifier.Chruby; @@ -31,24 +38,12 @@ suite("Ruby environment activation", () => { }, } as unknown as vscode.WorkspaceConfiguration); - const workspacePath = path.dirname( - path.dirname(path.dirname(path.dirname(__dirname))), - ); - const context = { extensionMode: vscode.ExtensionMode.Test, } as vscode.ExtensionContext; const outputChannel = new WorkspaceChannel("fake", LOG_CHANNEL); - ruby = new Ruby( - context, - { - uri: vscode.Uri.file(workspacePath), - name: path.basename(workspacePath), - index: 0, - } as vscode.WorkspaceFolder, - outputChannel, - ); + const ruby = new Ruby(context, workspaceFolder, outputChannel); await ruby.activateRuby(); assert.ok(ruby.rubyVersion, "Expected Ruby version to be set"); @@ -60,4 +55,44 @@ suite("Ruby environment activation", () => { configStub.restore(); }).timeout(10000); + + test("Deletes verbose and GC settings from activated environment", async () => { + const manager = process.env.CI + ? ManagerIdentifier.None + : ManagerIdentifier.Chruby; + + const configStub = sinon + .stub(vscode.workspace, "getConfiguration") + .returns({ + get: (name: string) => { + if (name === "rubyVersionManager") { + return manager; + } else if (name === "bundleGemfile") { + return ""; + } + + return undefined; + }, + } as unknown as vscode.WorkspaceConfiguration); + + const context = { + extensionMode: vscode.ExtensionMode.Test, + } as vscode.ExtensionContext; + const outputChannel = new WorkspaceChannel("fake", LOG_CHANNEL); + + const ruby = new Ruby(context, workspaceFolder, outputChannel); + + process.env.VERBOSE = "1"; + process.env.DEBUG = "WARN"; + process.env.RUBY_GC_HEAP_GROWTH_FACTOR = "1.7"; + await ruby.activateRuby(); + + assert.strictEqual(ruby.env.VERBOSE, undefined); + assert.strictEqual(ruby.env.DEBUG, undefined); + assert.strictEqual(ruby.env.RUBY_GC_HEAP_GROWTH_FACTOR, undefined); + delete process.env.VERBOSE; + delete process.env.DEBUG; + delete process.env.RUBY_GC_HEAP_GROWTH_FACTOR; + configStub.restore(); + }); });