Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow rzls to launch using standard dotnet (Redo) #6844

Merged
merged 3 commits into from
Feb 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion l10n/bundle.l10n.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
"Cannot load Razor language server because the directory was not found: '{0}'": "Cannot load Razor language server because the directory was not found: '{0}'",
"Could not find '{0}' in or above '{1}'.": "Could not find '{0}' in or above '{1}'.",
"Invalid razor.server.trace setting. Defaulting to '{0}'": "Invalid razor.server.trace setting. Defaulting to '{0}'",
"Could not find Razor Language Server executable within directory '{0}'": "Could not find Razor Language Server executable within directory '{0}'",
"Could not find Razor Language Server executable '{0}' within directory": "Could not find Razor Language Server executable '{0}' within directory",
"Server failed to start after retrying 5 times.": "Server failed to start after retrying 5 times.",
"Razor Language Server failed to start unexpectedly, please check the 'Razor Log' and report an issue.": "Razor Language Server failed to start unexpectedly, please check the 'Razor Log' and report an issue.",
"Tried to send requests while server is not started.": "Tried to send requests while server is not started.",
Expand Down
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
26 changes: 10 additions & 16 deletions src/razor/src/razorLanguageServerOptionsResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,23 +35,17 @@ export function resolveRazorLanguageServerOptions(
}

function findLanguageServerExecutable(withinDir: string) {
const extension = isWindows() ? '.exe' : '';
const executablePath = path.join(withinDir, `rzls${extension}`);
let fullPath = '';

if (fs.existsSync(executablePath)) {
fullPath = executablePath;
} 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)
);
}
// Prefer using executable over fallback to dll.
const fileName = isWindows() ? 'rzls.exe' : 'rzls';
let fullPath = path.join(withinDir, fileName);
if (!fs.existsSync(fullPath)) {
fullPath = path.join(withinDir, 'rzls.dll');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a note here - it is possible to publish a non-self contained executable if you wanted to
https://learn.microsoft.com/en-us/dotnet/core/deploying/#publish-framework-dependent

The benefit of the executable is that your process name is the executable name. Whereas if you launch with dotnet rzls.dll your executable name will be 'dotnet'

}

fullPath = dllPath;
if (!fs.existsSync(fullPath)) {
throw new Error(
vscode.l10n.t("Could not find Razor Language Server executable '{0}' within directory", fullPath)
);
}

return fullPath;
Expand Down
Loading