From 27c5cd1a1ef9c074f28c1da2ae43ed5d3aef94f2 Mon Sep 17 00:00:00 2001 From: Maryam Ariyan Date: Thu, 1 Feb 2024 02:52:36 -0800 Subject: [PATCH] Allow rzls to launch using standard dotnet (Redo) - Updates where to pick up dotnet.exe. - Contributes to making rzls move away from being self-contained. - Unifies how roslyn and razor servers acquire dotnet path/env variables. - Picks up leftover changes from https://github.com/dotnet/vscode-csharp/pull/5855 into main --- .../dotnetRuntimeExtensionResolver.ts | 21 +++++++++++++++- src/lsptoolshost/roslynLanguageServer.ts | 24 ++----------------- src/razor/src/extension.ts | 13 ++-------- .../src/razorLanguageServerOptionsResolver.ts | 23 +++++++----------- 4 files changed, 32 insertions(+), 49 deletions(-) diff --git a/src/lsptoolshost/dotnetRuntimeExtensionResolver.ts b/src/lsptoolshost/dotnetRuntimeExtensionResolver.ts index 08a0152f1..c7e75599f 100644 --- a/src/lsptoolshost/dotnetRuntimeExtensionResolver.ts +++ b/src/lsptoolshost/dotnetRuntimeExtensionResolver.ts @@ -9,7 +9,7 @@ import * as semver from 'semver'; import { HostExecutableInformation } from '../shared/constants/hostExecutableInformation'; import { IHostExecutableResolver } from '../shared/constants/IHostExecutableResolver'; import { PlatformInformation } from '../shared/platform'; -import { commonOptions } from '../shared/options'; +import { commonOptions, languageServerOptions } from '../shared/options'; import { existsSync } from 'fs'; import { CSharpExtensionId } from '../constants/csharpExtensionId'; import { getDotnetInfo } from '../shared/utils/getDotnetInfo'; @@ -67,6 +67,25 @@ export class DotnetRuntimeExtensionResolver implements IHostExecutableResolver { throw new Error(`Cannot find dotnet path '${dotnetExecutablePath}'`); } + // Take care to always run .NET processes on the runtime that we intend. + // The dotnet.exe we point to should not go looking for other runtimes. + const env: NodeJS.ProcessEnv = { ...process.env }; + env.DOTNET_ROOT = path.dirname(dotnetExecutablePath); + env.DOTNET_MULTILEVEL_LOOKUP = '0'; + // Save user's DOTNET_ROOT env-var value so server can recover the user setting when needed + env.DOTNET_ROOT_USER = process.env.DOTNET_ROOT ?? 'EMPTY'; + + if (languageServerOptions.crashDumpPath) { + // Enable dump collection + env.DOTNET_DbgEnableMiniDump = '1'; + // Collect heap dump + env.DOTNET_DbgMiniDumpType = '2'; + // Collect crashreport.json with additional thread and stack frame information. + env.DOTNET_EnableCrashReport = '1'; + // The dump file name format is ..dmp + env.DOTNET_DbgMiniDumpName = path.join(languageServerOptions.crashDumpPath, '%e.%p.dmp'); + } + return { version: '' /* We don't need to know the version - we've already downloaded the correct one */, path: dotnetExecutablePath, diff --git a/src/lsptoolshost/roslynLanguageServer.ts b/src/lsptoolshost/roslynLanguageServer.ts index 3eb46c4f0..fdbfe021f 100644 --- a/src/lsptoolshost/roslynLanguageServer.ts +++ b/src/lsptoolshost/roslynLanguageServer.ts @@ -491,30 +491,10 @@ export class RoslynLanguageServer { const serverPath = getServerPath(platformInfo); const dotnetInfo = await hostExecutableResolver.getHostExecutableInfo(); - const dotnetRuntimePath = path.dirname(dotnetInfo.path); const dotnetExecutablePath = dotnetInfo.path; _channel.appendLine('Dotnet path: ' + dotnetExecutablePath); - // Take care to always run .NET processes on the runtime that we intend. - // The dotnet.exe we point to should not go looking for other runtimes. - const env: NodeJS.ProcessEnv = { ...process.env }; - env.DOTNET_ROOT = dotnetRuntimePath; - env.DOTNET_MULTILEVEL_LOOKUP = '0'; - // Save user's DOTNET_ROOT env-var value so server can recover the user setting when needed - env.DOTNET_ROOT_USER = process.env.DOTNET_ROOT ?? 'EMPTY'; - - if (languageServerOptions.crashDumpPath) { - // Enable dump collection - env.DOTNET_DbgEnableMiniDump = '1'; - // Collect heap dump - env.DOTNET_DbgMiniDumpType = '2'; - // Collect crashreport.json with additional thread and stack frame information. - env.DOTNET_EnableCrashReport = '1'; - // The dump file name format is ..dmp - env.DOTNET_DbgMiniDumpName = path.join(languageServerOptions.crashDumpPath, '%e.%p.dmp'); - } - let args: string[] = []; if (commonOptions.waitForDebugger) { @@ -557,7 +537,7 @@ export class RoslynLanguageServer { const csharpDevKitArgs = this.getCSharpDevKitExportArgs(); args = args.concat(csharpDevKitArgs); - await this.setupDevKitEnvironment(env, csharpDevkitExtension); + await this.setupDevKitEnvironment(dotnetInfo.env, csharpDevkitExtension); } else { // C# Dev Kit is not installed - continue C#-only activation. _channel.appendLine('Activating C# standalone...'); @@ -580,7 +560,7 @@ export class RoslynLanguageServer { const cpOptions: cp.SpawnOptionsWithoutStdio = { detached: true, windowsHide: true, - env: env, + env: dotnetInfo.env, }; if (serverPath.endsWith('.dll')) { diff --git a/src/razor/src/extension.ts b/src/razor/src/extension.ts index ad888d45d..48f65b4ad 100644 --- a/src/razor/src/extension.ts +++ b/src/razor/src/extension.ts @@ -90,20 +90,11 @@ export async function activate( ); const dotnetInfo = await hostExecutableResolver.getHostExecutableInfo(); - const dotnetRuntimePath = path.dirname(dotnetInfo.path); - - // Take care to always run .NET processes on the runtime that we intend. - // The dotnet.exe we point to should not go looking for other runtimes. - const env: NodeJS.ProcessEnv = { ...process.env }; - env.DOTNET_ROOT = dotnetRuntimePath; - env.DOTNET_MULTILEVEL_LOOKUP = '0'; - // Save user's DOTNET_ROOT env-var value so server can recover the user setting when needed - env.DOTNET_ROOT_USER = process.env.DOTNET_ROOT ?? 'EMPTY'; let telemetryExtensionDllPath = ''; // Set up DevKit environment for telemetry if (csharpDevkitExtension) { - await setupDevKitEnvironment(env, csharpDevkitExtension, logger); + await setupDevKitEnvironment(dotnetInfo.env, csharpDevkitExtension, logger); const telemetryExtensionPath = path.join( util.getExtensionPath(), @@ -121,7 +112,7 @@ export async function activate( razorTelemetryReporter, vscodeTelemetryReporter, telemetryExtensionDllPath, - env, + dotnetInfo.env, dotnetInfo.path, logger ); diff --git a/src/razor/src/razorLanguageServerOptionsResolver.ts b/src/razor/src/razorLanguageServerOptionsResolver.ts index b9ccdfc45..e1730120d 100644 --- a/src/razor/src/razorLanguageServerOptionsResolver.ts +++ b/src/razor/src/razorLanguageServerOptionsResolver.ts @@ -7,7 +7,6 @@ import * as fs from 'fs'; import * as os from 'os'; import * as path from 'path'; import * as vscodeAdapter from './vscodeAdapter'; -import * as vscode from 'vscode'; import { RazorLanguageServerOptions } from './razorLanguageServerOptions'; import { RazorLogger } from './razorLogger'; import { LogLevel } from './logLevel'; @@ -35,23 +34,17 @@ export function resolveRazorLanguageServerOptions( } function findLanguageServerExecutable(withinDir: string) { - const extension = isWindows() ? '.exe' : ''; - const executablePath = path.join(withinDir, `rzls${extension}`); + const isSelfContained = fs.existsSync(path.join(withinDir, 'coreclr.dll')); let fullPath = ''; - - if (fs.existsSync(executablePath)) { - fullPath = executablePath; + if (isSelfContained) { + const fileName = isWindows() ? 'rzls.exe' : 'rzls'; + fullPath = path.join(withinDir, fileName); } else { - // Exe doesn't exist. - const dllPath = path.join(withinDir, 'rzls.dll'); - - if (!fs.existsSync(dllPath)) { - throw new Error( - vscode.l10n.t("Could not find Razor Language Server executable within directory '{0}'", withinDir) - ); - } + fullPath = path.join(withinDir, 'rzls.dll'); + } - fullPath = dllPath; + if (!fs.existsSync(fullPath)) { + throw new Error(`Could not find Razor Language Server executable within directory '${withinDir}'`); } return fullPath;