@@ -8,36 +8,71 @@ import { RoslynLanguageServer } from '../roslynLanguageServer';
8
8
import { VSGetProjectContextsRequest , VSProjectContext , VSProjectContextList } from '../roslynProtocol' ;
9
9
import { TextDocumentIdentifier } from 'vscode-languageserver-protocol' ;
10
10
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
+ }
11
18
12
19
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 ( ) ;
15
22
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
+ } ) ;
17
32
18
- clear ( ) {
19
- this . _projectContexts = { } ;
33
+ vscode . window . onDidChangeActiveTextEditor ( this . refresh ) ;
20
34
}
21
35
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 ;
25
38
}
26
39
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 ;
39
44
}
40
45
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
+ ) ;
42
77
}
43
78
}
0 commit comments