Skip to content

Commit 3fc374c

Browse files
authored
Merge pull request #7652 from dotnet/dev/jorobich/warn-misc-files
Add miscellaneous file open notifications
2 parents b4591f3 + 321ffe3 commit 3fc374c

File tree

7 files changed

+96
-10
lines changed

7 files changed

+96
-10
lines changed

l10n/bundle.l10n.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,9 @@
172172
"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?",
173173
"Nested Code Action": "Nested Code Action",
174174
"Fix All: ": "Fix All: ",
175+
"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.",
176+
"Dismiss": "Dismiss",
177+
"Do not show for this workspace": "Do not show for this workspace",
175178
"Open solution": "Open solution",
176179
"Restart server": "Restart server",
177180
"C# Workspace Status": "C# Workspace Status",

package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1479,6 +1479,11 @@
14791479
"default": false,
14801480
"description": "%configuration.dotnet.server.suppressLspErrorToasts%"
14811481
},
1482+
"dotnet.server.suppressMiscellaneousFilesToasts": {
1483+
"type": "boolean",
1484+
"default": false,
1485+
"description": "%configuration.dotnet.server.suppressMiscellaneousFilesToasts%"
1486+
},
14821487
"dotnet.server.useServerGC": {
14831488
"type": "boolean",
14841489
"default": true,

package.nls.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
"configuration.dotnet.server.extensionPaths": "Override for path to language server --extension arguments",
3636
"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.",
3737
"configuration.dotnet.server.suppressLspErrorToasts": "Suppresses error toasts from showing up if the server encounters a recoverable error.",
38+
"configuration.dotnet.server.suppressMiscellaneousFilesToasts": "Suppress warning toasts from showing up if the active document is outside the open workspace.",
3839
"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.",
3940
"configuration.dotnet.enableXamlTools": "Enables XAML tools when using C# Dev Kit",
4041
"configuration.dotnet.projects.enableAutomaticRestore": "Enables automatic NuGet restore if the extension detects assets are missing.",

src/lsptoolshost/languageStatusBar.ts

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,11 @@ import { ServerState } from './serverStateChange';
1111
import { getCSharpDevKit } from '../utils/getCSharpDevKit';
1212
import { RazorLanguage } from '../razor/src/razorLanguage';
1313

14-
let currentServerState: ServerState = ServerState.Stopped;
15-
1614
export function registerLanguageStatusItems(
1715
context: vscode.ExtensionContext,
1816
languageServer: RoslynLanguageServer,
1917
languageServerEvents: RoslynLanguageServerEvents
2018
) {
21-
// Track the current server state.
22-
languageServerEvents.onServerStateChange((e) => {
23-
currentServerState = e.state;
24-
});
25-
2619
// DevKit will provide an equivalent workspace status item.
2720
if (!getCSharpDevKit()) {
2821
WorkspaceStatus.createStatusItem(context, languageServerEvents);
@@ -85,13 +78,19 @@ class ProjectContextStatus {
8578

8679
// Show a warning when the active file is part of the Miscellaneous File workspace and
8780
// project initialization is complete.
88-
if (currentServerState === ServerState.ProjectInitializationComplete) {
81+
if (languageServer.state === ServerState.ProjectInitializationComplete) {
8982
item.severity = e.context._vs_is_miscellaneous
9083
? vscode.LanguageStatusSeverity.Warning
9184
: vscode.LanguageStatusSeverity.Information;
9285
} else {
9386
item.severity = vscode.LanguageStatusSeverity.Information;
9487
}
88+
89+
item.detail = e.context._vs_is_miscellaneous
90+
? vscode.l10n.t(
91+
'The active document is not part of the open workspace. Not all language features will be available.'
92+
)
93+
: vscode.l10n.t('Active File Context');
9594
});
9695

9796
// Trigger a refresh, but don't block creation on the refresh completing.
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import * as vscode from 'vscode';
7+
import * as crypto from 'crypto';
8+
import { RoslynLanguageServer } from './roslynLanguageServer';
9+
import { ActionOption, showWarningMessage } from '../shared/observers/utils/showMessage';
10+
import { ServerState } from './serverStateChange';
11+
import { languageServerOptions } from '../shared/options';
12+
13+
const SuppressMiscellaneousFilesToastsOption = 'dotnet.server.suppressMiscellaneousFilesToasts';
14+
const NotifiedDocuments = new Set<string>();
15+
16+
export function registerMiscellaneousFileNotifier(
17+
context: vscode.ExtensionContext,
18+
languageServer: RoslynLanguageServer
19+
) {
20+
languageServer._projectContextService.onActiveFileContextChanged((e) => {
21+
// Only warn for miscellaneous files when the workspace is fully initialized.
22+
if (!e.context._vs_is_miscellaneous || languageServer.state !== ServerState.ProjectInitializationComplete) {
23+
return;
24+
}
25+
26+
// Check settings and workspaceState to see if we should suppress the toast.
27+
if (
28+
languageServerOptions.suppressMiscellaneousFilesToasts ||
29+
context.workspaceState.get<boolean>(SuppressMiscellaneousFilesToastsOption, false)
30+
) {
31+
return;
32+
}
33+
34+
// Check to see if we have already notified the user about this document.
35+
const hash = createHash(e.uri.toString(/*skipEncoding:*/ true));
36+
if (NotifiedDocuments.has(hash)) {
37+
return;
38+
} else {
39+
NotifiedDocuments.add(hash);
40+
}
41+
42+
const message = vscode.l10n.t(
43+
'The active document is not part of the open workspace. Not all language features will be available.'
44+
);
45+
const dismissItem = vscode.l10n.t('Dismiss');
46+
// Provide the user a way to easily disable the toast without changing settings.
47+
const disableWorkspace: ActionOption = {
48+
title: vscode.l10n.t('Do not show for this workspace'),
49+
action: async () => {
50+
context.workspaceState.update(SuppressMiscellaneousFilesToastsOption, true);
51+
},
52+
};
53+
showWarningMessage(vscode, message, dismissItem, disableWorkspace);
54+
});
55+
}
56+
57+
function createHash(data: string): string {
58+
return crypto.createHash('sha256').update(data).digest('hex');
59+
}

src/lsptoolshost/roslynLanguageServer.ts

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ import {
7575
showInformationMessage,
7676
} from '../shared/observers/utils/showMessage';
7777
import { registerSourceGeneratedFilesContentProvider } from './sourceGeneratedFilesContentProvider';
78+
import { registerMiscellaneousFileNotifier } from './miscellaneousFileNotifier';
7879

7980
let _channel: vscode.OutputChannel;
8081
let _traceChannel: vscode.OutputChannel;
@@ -115,8 +116,10 @@ export class RoslynLanguageServer {
115116

116117
public readonly _onAutoInsertFeature: OnAutoInsertFeature;
117118

118-
public _buildDiagnosticService: BuildDiagnosticsService;
119-
public _projectContextService: ProjectContextService;
119+
public readonly _buildDiagnosticService: BuildDiagnosticsService;
120+
public readonly _projectContextService: ProjectContextService;
121+
122+
private _state: ServerState = ServerState.Stopped;
120123

121124
constructor(
122125
private _languageClient: RoslynLanguageClient,
@@ -129,6 +132,7 @@ export class RoslynLanguageServer {
129132
this.registerSendOpenSolution();
130133
this.registerProjectInitialization();
131134
this.registerServerStateChanged();
135+
this.registerServerStateTracking();
132136
this.registerReportProjectConfiguration();
133137
this.registerExtensionsChanged();
134138
this.registerTelemetryChanged();
@@ -151,6 +155,10 @@ export class RoslynLanguageServer {
151155
this._onAutoInsertFeature = new OnAutoInsertFeature(this._languageClient);
152156
}
153157

158+
public get state(): ServerState {
159+
return this._state;
160+
}
161+
154162
private registerSetTrace() {
155163
// Set the language client trace level based on the log level option.
156164
// setTrace only works after the client is already running.
@@ -179,6 +187,12 @@ export class RoslynLanguageServer {
179187
});
180188
}
181189

190+
private registerServerStateTracking() {
191+
this._languageServerEvents.onServerStateChange((e) => {
192+
this._state = e.state;
193+
});
194+
}
195+
182196
private registerSendOpenSolution() {
183197
this._languageClient.onDidChangeState(async (state) => {
184198
if (state.newState === State.Running) {
@@ -1053,6 +1067,7 @@ export async function activateRoslynLanguageServer(
10531067
);
10541068

10551069
registerLanguageStatusItems(context, languageServer, languageServerEvents);
1070+
registerMiscellaneousFileNotifier(context, languageServer);
10561071
registerCopilotExtension(languageServer, _channel);
10571072

10581073
// Register any commands that need to be handled by the extension.

src/shared/options.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ export interface LanguageServerOptions {
8080
readonly componentPaths: { [key: string]: string } | null;
8181
readonly enableXamlTools: boolean;
8282
readonly suppressLspErrorToasts: boolean;
83+
readonly suppressMiscellaneousFilesToasts: boolean;
8384
readonly useServerGC: boolean;
8485
}
8586

@@ -411,6 +412,9 @@ class LanguageServerOptionsImpl implements LanguageServerOptions {
411412
public get suppressLspErrorToasts() {
412413
return readOption<boolean>('dotnet.server.suppressLspErrorToasts', false);
413414
}
415+
public get suppressMiscellaneousFilesToasts() {
416+
return readOption<boolean>('dotnet.server.suppressMiscellaneousFilesToasts', false);
417+
}
414418
public get useServerGC() {
415419
return readOption<boolean>('dotnet.server.useServerGC', true);
416420
}

0 commit comments

Comments
 (0)