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

Add miscellaneous file open notifications #7652

Merged
merged 3 commits into from
Oct 11, 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
3 changes: 3 additions & 0 deletions l10n/bundle.l10n.json
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,9 @@
"C# configuration has changed. Would you like to reload the window to apply your changes?": "C# configuration has changed. Would you like to reload the window to apply your changes?",
"Nested Code Action": "Nested Code Action",
"Fix All: ": "Fix All: ",
"The active document is not part of the open workspace. Not all language features will be available.": "The active document is not part of the open workspace. Not all language features will be available.",
"Dismiss": "Dismiss",
"Do not show for this workspace": "Do not show for this workspace",
"Open solution": "Open solution",
"Restart server": "Restart server",
"C# Workspace Status": "C# Workspace Status",
Expand Down
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -1479,6 +1479,11 @@
"default": false,
"description": "%configuration.dotnet.server.suppressLspErrorToasts%"
},
"dotnet.server.suppressMiscellaneousFilesToasts": {
"type": "boolean",
"default": false,
"description": "%configuration.dotnet.server.suppressMiscellaneousFilesToasts%"
},
"dotnet.server.useServerGC": {
"type": "boolean",
"default": true,
Expand Down
1 change: 1 addition & 0 deletions package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"configuration.dotnet.server.extensionPaths": "Override for path to language server --extension arguments",
"configuration.dotnet.server.crashDumpPath": "Sets a folder path where crash dumps are written to if the language server crashes. Must be writeable by the user.",
"configuration.dotnet.server.suppressLspErrorToasts": "Suppresses error toasts from showing up if the server encounters a recoverable error.",
"configuration.dotnet.server.suppressMiscellaneousFilesToasts": "Suppress warning toasts from showing up if the active document is outside the open workspace.",
"configuration.dotnet.server.useServerGC": "Configure the language server to use .NET server garbage collection. Server garbage collection generally provides better performance at the expensive of higher memory consumption.",
"configuration.dotnet.enableXamlTools": "Enables XAML tools when using C# Dev Kit",
"configuration.dotnet.projects.enableAutomaticRestore": "Enables automatic NuGet restore if the extension detects assets are missing.",
Expand Down
15 changes: 7 additions & 8 deletions src/lsptoolshost/languageStatusBar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,11 @@ import { ServerState } from './serverStateChange';
import { getCSharpDevKit } from '../utils/getCSharpDevKit';
import { RazorLanguage } from '../razor/src/razorLanguage';

let currentServerState: ServerState = ServerState.Stopped;

export function registerLanguageStatusItems(
context: vscode.ExtensionContext,
languageServer: RoslynLanguageServer,
languageServerEvents: RoslynLanguageServerEvents
) {
// Track the current server state.
languageServerEvents.onServerStateChange((e) => {
currentServerState = e.state;
});

// DevKit will provide an equivalent workspace status item.
if (!getCSharpDevKit()) {
WorkspaceStatus.createStatusItem(context, languageServerEvents);
Expand Down Expand Up @@ -85,13 +78,19 @@ class ProjectContextStatus {

// Show a warning when the active file is part of the Miscellaneous File workspace and
// project initialization is complete.
if (currentServerState === ServerState.ProjectInitializationComplete) {
if (languageServer.state === ServerState.ProjectInitializationComplete) {
item.severity = e.context._vs_is_miscellaneous
? vscode.LanguageStatusSeverity.Warning
: vscode.LanguageStatusSeverity.Information;
} else {
item.severity = vscode.LanguageStatusSeverity.Information;
}

item.detail = e.context._vs_is_miscellaneous
? vscode.l10n.t(
'The active document is not part of the open workspace. Not all language features will be available.'
)
: vscode.l10n.t('Active File Context');
});

// Trigger a refresh, but don't block creation on the refresh completing.
Expand Down
59 changes: 59 additions & 0 deletions src/lsptoolshost/miscellaneousFileNotifier.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import * as vscode from 'vscode';
import * as crypto from 'crypto';
import { RoslynLanguageServer } from './roslynLanguageServer';
import { ActionOption, showWarningMessage } from '../shared/observers/utils/showMessage';
import { ServerState } from './serverStateChange';
import { languageServerOptions } from '../shared/options';

const SuppressMiscellaneousFilesToastsOption = 'dotnet.server.suppressMiscellaneousFilesToasts';
const NotifiedDocuments = new Set<string>();

export function registerMiscellaneousFileNotifier(
context: vscode.ExtensionContext,
languageServer: RoslynLanguageServer
) {
languageServer._projectContextService.onActiveFileContextChanged((e) => {
// Only warn for miscellaneous files when the workspace is fully initialized.
if (!e.context._vs_is_miscellaneous || languageServer.state !== ServerState.ProjectInitializationComplete) {
return;
}

// Check settings and workspaceState to see if we should suppress the toast.
if (
languageServerOptions.suppressMiscellaneousFilesToasts ||
context.workspaceState.get<boolean>(SuppressMiscellaneousFilesToastsOption, false)
) {
return;
}

// Check to see if we have already notified the user about this document.
const hash = createHash(e.uri.toString(/*skipEncoding:*/ true));
if (NotifiedDocuments.has(hash)) {
return;
} else {
NotifiedDocuments.add(hash);
}

const message = vscode.l10n.t(
'The active document is not part of the open workspace. Not all language features will be available.'
Copy link
Member

Choose a reason for hiding this comment

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

I was wondering if we wanted to add like a learn more docs link with how they might tell why the file is in misc. For example, making sure the file is part of a project, making sure the language server has a project loaded, making sure the project is part of the loaded sln, etc.

Copy link
Member Author

@JoeRobich JoeRobich Oct 10, 2024

Choose a reason for hiding this comment

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

I think that is a good idea and we can do it in a follow up.

@webreidi I see VS has a page on Misc Files. Is that a good one to link to for now? Should we have a C# ext. centric page created?

Copy link
Member Author

Choose a reason for hiding this comment

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

Created draft PR #7654 to explore this further.

Choose a reason for hiding this comment

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

I think the VS Link will only cause confusion. But we can add to the FAQ the specifics of this.

);
const dismissItem = vscode.l10n.t('Dismiss');
// Provide the user a way to easily disable the toast without changing settings.
const disableWorkspace: ActionOption = {
title: vscode.l10n.t('Do not show for this workspace'),
action: async () => {
context.workspaceState.update(SuppressMiscellaneousFilesToastsOption, true);
},
};
showWarningMessage(vscode, message, dismissItem, disableWorkspace);
});
}

function createHash(data: string): string {
return crypto.createHash('sha256').update(data).digest('hex');
}
19 changes: 17 additions & 2 deletions src/lsptoolshost/roslynLanguageServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ import {
showInformationMessage,
} from '../shared/observers/utils/showMessage';
import { registerSourceGeneratedFilesContentProvider } from './sourceGeneratedFilesContentProvider';
import { registerMiscellaneousFileNotifier } from './miscellaneousFileNotifier';

let _channel: vscode.OutputChannel;
let _traceChannel: vscode.OutputChannel;
Expand Down Expand Up @@ -115,8 +116,10 @@ export class RoslynLanguageServer {

public readonly _onAutoInsertFeature: OnAutoInsertFeature;

public _buildDiagnosticService: BuildDiagnosticsService;
public _projectContextService: ProjectContextService;
public readonly _buildDiagnosticService: BuildDiagnosticsService;
public readonly _projectContextService: ProjectContextService;

private _state: ServerState = ServerState.Stopped;

constructor(
private _languageClient: RoslynLanguageClient,
Expand All @@ -129,6 +132,7 @@ export class RoslynLanguageServer {
this.registerSendOpenSolution();
this.registerProjectInitialization();
this.registerServerStateChanged();
this.registerServerStateTracking();
this.registerReportProjectConfiguration();
this.registerExtensionsChanged();
this.registerTelemetryChanged();
Expand All @@ -151,6 +155,10 @@ export class RoslynLanguageServer {
this._onAutoInsertFeature = new OnAutoInsertFeature(this._languageClient);
}

public get state(): ServerState {
return this._state;
}

private registerSetTrace() {
// Set the language client trace level based on the log level option.
// setTrace only works after the client is already running.
Expand Down Expand Up @@ -179,6 +187,12 @@ export class RoslynLanguageServer {
});
}

private registerServerStateTracking() {
this._languageServerEvents.onServerStateChange((e) => {
this._state = e.state;
});
}

private registerSendOpenSolution() {
this._languageClient.onDidChangeState(async (state) => {
if (state.newState === State.Running) {
Expand Down Expand Up @@ -1053,6 +1067,7 @@ export async function activateRoslynLanguageServer(
);

registerLanguageStatusItems(context, languageServer, languageServerEvents);
registerMiscellaneousFileNotifier(context, languageServer);
registerCopilotExtension(languageServer, _channel);

// Register any commands that need to be handled by the extension.
Expand Down
4 changes: 4 additions & 0 deletions src/shared/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ export interface LanguageServerOptions {
readonly componentPaths: { [key: string]: string } | null;
readonly enableXamlTools: boolean;
readonly suppressLspErrorToasts: boolean;
readonly suppressMiscellaneousFilesToasts: boolean;
readonly useServerGC: boolean;
}

Expand Down Expand Up @@ -411,6 +412,9 @@ class LanguageServerOptionsImpl implements LanguageServerOptions {
public get suppressLspErrorToasts() {
return readOption<boolean>('dotnet.server.suppressLspErrorToasts', false);
}
public get suppressMiscellaneousFilesToasts() {
return readOption<boolean>('dotnet.server.suppressMiscellaneousFilesToasts', false);
}
public get useServerGC() {
return readOption<boolean>('dotnet.server.useServerGC', true);
}
Expand Down
Loading