Skip to content

Commit

Permalink
Allow rzls to launch using standard dotnet (Redo)
Browse files Browse the repository at this point in the history
- 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 #5855 into main
  • Loading branch information
maryamariyan committed Feb 1, 2024
1 parent 26d9328 commit 27c5cd1
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 49 deletions.
21 changes: 20 additions & 1 deletion src/lsptoolshost/dotnetRuntimeExtensionResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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 <executable>.<pid>.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,
Expand Down
24 changes: 2 additions & 22 deletions src/lsptoolshost/roslynLanguageServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 <executable>.<pid>.dmp
env.DOTNET_DbgMiniDumpName = path.join(languageServerOptions.crashDumpPath, '%e.%p.dmp');
}

let args: string[] = [];

if (commonOptions.waitForDebugger) {
Expand Down Expand Up @@ -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...');
Expand All @@ -580,7 +560,7 @@ export class RoslynLanguageServer {
const cpOptions: cp.SpawnOptionsWithoutStdio = {
detached: true,
windowsHide: true,
env: env,
env: dotnetInfo.env,
};

if (serverPath.endsWith('.dll')) {
Expand Down
13 changes: 2 additions & 11 deletions src/razor/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand All @@ -121,7 +112,7 @@ export async function activate(
razorTelemetryReporter,
vscodeTelemetryReporter,
telemetryExtensionDllPath,
env,
dotnetInfo.env,
dotnetInfo.path,
logger
);
Expand Down
23 changes: 8 additions & 15 deletions src/razor/src/razorLanguageServerOptionsResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 27c5cd1

Please sign in to comment.