@@ -8,36 +8,71 @@ import { RoslynLanguageServer } from '../roslynLanguageServer';
88import { VSGetProjectContextsRequest , VSProjectContext , VSProjectContextList } from '../roslynProtocol' ;
99import { TextDocumentIdentifier } from 'vscode-languageserver-protocol' ;
1010import { 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
1219export 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