Skip to content

Commit fb0b3c4

Browse files
committed
Remove caching and add onChange event.
1 parent 3cf6388 commit fb0b3c4

File tree

4 files changed

+64
-50
lines changed

4 files changed

+64
-50
lines changed

l10n/bundle.l10n.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@
162162
"C# Workspace Status": "C# Workspace Status",
163163
"Open solution": "Open solution",
164164
"C# Project Context Status": "C# Project Context Status",
165-
"Project Context": "Project Context",
165+
"Active File Context": "Active File Context",
166166
"Pick a fix all scope": "Pick a fix all scope",
167167
"Fix All Code Action": "Fix All Code Action",
168168
"pipeArgs must be a string or a string array type": "pipeArgs must be a string or a string array type",

src/lsptoolshost/languageStatusBar.ts

Lines changed: 6 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export function registerLanguageStatusItems(
1919
if (!getCSharpDevKit()) {
2020
WorkspaceStatus.createStatusItem(context, languageServerEvents);
2121
}
22-
ProjectContextStatus.createStatusItem(context, languageServer, languageServerEvents);
22+
ProjectContextStatus.createStatusItem(context, languageServer);
2323
}
2424

2525
class WorkspaceStatus {
@@ -43,41 +43,20 @@ class WorkspaceStatus {
4343
}
4444

4545
class ProjectContextStatus {
46-
static createStatusItem(
47-
context: vscode.ExtensionContext,
48-
languageServer: RoslynLanguageServer,
49-
languageServerEvents: RoslynLanguageServerEvents
50-
) {
46+
static createStatusItem(context: vscode.ExtensionContext, languageServer: RoslynLanguageServer) {
5147
const projectContextService = languageServer._projectContextService;
5248

5349
const item = vscode.languages.createLanguageStatusItem(
5450
'csharp.projectContextStatus',
5551
languageServerOptions.documentSelector
5652
);
5753
item.name = vscode.l10n.t('C# Project Context Status');
58-
item.detail = vscode.l10n.t('Project Context');
54+
item.detail = vscode.l10n.t('Active File Context');
5955
context.subscriptions.push(item);
6056

61-
updateItem(vscode.window.activeTextEditor);
62-
context.subscriptions.push(vscode.window.onDidChangeActiveTextEditor(updateItem));
63-
64-
languageServerEvents.onServerStateChange((e) => {
65-
if (e.state === ServerState.ProjectInitializationComplete) {
66-
projectContextService.clear();
67-
updateItem(vscode.window.activeTextEditor);
68-
}
57+
projectContextService.onActiveFileContextChanged((e) => {
58+
item.text = e.context._vs_label;
6959
});
70-
71-
async function updateItem(e: vscode.TextEditor | undefined) {
72-
if (e?.document.languageId !== 'csharp') {
73-
item.text = '';
74-
return;
75-
}
76-
77-
const projectContext = await projectContextService.getCurrentProjectContext(e.document.uri);
78-
if (projectContext) {
79-
item.text = projectContext._vs_label;
80-
}
81-
}
60+
projectContextService.refresh();
8261
}
8362
}

src/lsptoolshost/roslynLanguageServer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ export class RoslynLanguageServer {
127127
this._buildDiagnosticService = new BuildDiagnosticsService(diagnosticsReportedByBuild);
128128
this.registerDocumentOpenForDiagnostics();
129129

130-
this._projectContextService = new ProjectContextService(this);
130+
this._projectContextService = new ProjectContextService(this, this._languageServerEvents);
131131

132132
// Register Razor dynamic file info handling
133133
this.registerDynamicFileInfo();

src/lsptoolshost/services/projectContextService.ts

Lines changed: 56 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,36 +8,71 @@ import { RoslynLanguageServer } from '../roslynLanguageServer';
88
import { VSGetProjectContextsRequest, VSProjectContext, VSProjectContextList } from '../roslynProtocol';
99
import { TextDocumentIdentifier } from 'vscode-languageserver-protocol';
1010
import { UriConverter } from '../uriConverter';
11+
import { LanguageServerEvents } from '../languageServerEvents';
12+
import { ServerState } from '../serverStateChange';
13+
14+
export interface ProjectContextChangeEvent {
15+
uri: vscode.Uri;
16+
context: VSProjectContext;
17+
}
1118

1219
export class ProjectContextService {
13-
/** Track the project contexts for a particular document uri. */
14-
private _projectContexts: { [uri: string]: Promise<VSProjectContextList> | VSProjectContextList } = {};
20+
private readonly _contextChangeEmitter = new vscode.EventEmitter<ProjectContextChangeEvent>();
21+
private _source = new vscode.CancellationTokenSource();
1522

16-
constructor(private languageServer: RoslynLanguageServer) {}
23+
constructor(private _languageServer: RoslynLanguageServer, _languageServerEvents: LanguageServerEvents) {
24+
_languageServerEvents.onServerStateChange((e) => {
25+
// When the project initialization is complete, open files
26+
// could move from the miscellaneous workspace context into
27+
// an open project.
28+
if (e.state === ServerState.ProjectInitializationComplete) {
29+
this.refresh();
30+
}
31+
});
1732

18-
clear() {
19-
this._projectContexts = {};
33+
vscode.window.onDidChangeActiveTextEditor(this.refresh);
2034
}
2135

22-
async getCurrentProjectContext(uri: string | vscode.Uri): Promise<VSProjectContext | undefined> {
23-
const projectContexts = await this.getProjectContexts(uri);
24-
return projectContexts?._vs_projectContexts[projectContexts._vs_defaultIndex];
36+
public get onActiveFileContextChanged(): vscode.Event<ProjectContextChangeEvent> {
37+
return this._contextChangeEmitter.event;
2538
}
2639

27-
async getProjectContexts(uri: string | vscode.Uri): Promise<VSProjectContextList | undefined> {
28-
const uriString = uri instanceof vscode.Uri ? UriConverter.serialize(uri) : uri;
29-
30-
if (!(uriString in this._projectContexts)) {
31-
const source = new vscode.CancellationTokenSource();
32-
this._projectContexts[uriString] = this.languageServer
33-
.sendRequest(
34-
VSGetProjectContextsRequest.type,
35-
{ _vs_textDocument: TextDocumentIdentifier.create(uriString) },
36-
source.token
37-
)
38-
.then((contextList) => (this._projectContexts[uriString] = contextList));
40+
public async refresh() {
41+
const textEditor = vscode.window.activeTextEditor;
42+
if (textEditor?.document?.languageId !== 'csharp') {
43+
return;
3944
}
4045

41-
return this._projectContexts[uriString];
46+
const uri = textEditor.document.uri;
47+
48+
// If we have an open request, cancel it.
49+
this._source.cancel();
50+
this._source = new vscode.CancellationTokenSource();
51+
52+
try {
53+
const contextList = await this.getProjectContexts(uri, this._source.token);
54+
if (!contextList) {
55+
return;
56+
}
57+
58+
const context = contextList._vs_projectContexts[contextList._vs_defaultIndex];
59+
this._contextChangeEmitter.fire({ uri, context });
60+
} catch {
61+
// This request was cancelled
62+
}
63+
}
64+
65+
private async getProjectContexts(
66+
uri: vscode.Uri,
67+
token: vscode.CancellationToken
68+
): Promise<VSProjectContextList | undefined> {
69+
const uriString = UriConverter.serialize(uri);
70+
const textDocument = TextDocumentIdentifier.create(uriString);
71+
72+
return this._languageServer.sendRequest(
73+
VSGetProjectContextsRequest.type,
74+
{ _vs_textDocument: textDocument },
75+
token
76+
);
4277
}
4378
}

0 commit comments

Comments
 (0)