@@ -10,12 +10,14 @@ import { TextDocumentIdentifier } from 'vscode-languageserver-protocol';
10
10
import { UriConverter } from '../uriConverter' ;
11
11
import { LanguageServerEvents } from '../languageServerEvents' ;
12
12
import { ServerState } from '../serverStateChange' ;
13
+ import { CancellationToken } from 'vscode-languageclient/node' ;
13
14
14
15
export interface ProjectContextChangeEvent {
15
16
languageId : string ;
16
17
uri : vscode . Uri ;
17
18
context : VSProjectContext ;
18
19
isVerified : boolean ;
20
+ hasAdditionalContexts : boolean ;
19
21
}
20
22
21
23
const VerificationDelay = 2 * 1000 ;
@@ -24,6 +26,7 @@ let _verifyTimeout: NodeJS.Timeout | undefined;
24
26
let _documentUriToVerify : vscode . Uri | undefined ;
25
27
26
28
export class ProjectContextService {
29
+ private readonly _projectContextMap : Map < string , VSProjectContext > = new Map ( ) ;
27
30
private readonly _contextChangeEmitter = new vscode . EventEmitter < ProjectContextChangeEvent > ( ) ;
28
31
private _source = new vscode . CancellationTokenSource ( ) ;
29
32
private readonly _emptyProjectContext : VSProjectContext = {
@@ -50,6 +53,53 @@ export class ProjectContextService {
50
53
return this . _contextChangeEmitter . event ;
51
54
}
52
55
56
+ public async getDocumentContext ( uri : string | vscode . Uri ) : Promise < VSProjectContext | undefined > ;
57
+ public async getDocumentContext (
58
+ uri : string | vscode . Uri ,
59
+ contextList ?: VSProjectContextList | undefined
60
+ ) : Promise < VSProjectContext > ;
61
+ public async getDocumentContext (
62
+ uri : string | vscode . Uri ,
63
+ contextList ?: VSProjectContextList | undefined
64
+ ) : Promise < VSProjectContext | undefined > {
65
+ // To find the current context for the specified document we need to know the list
66
+ // of contexts that it is a part of.
67
+ contextList ??= await this . getProjectContexts ( uri , CancellationToken . None ) ;
68
+ if ( contextList === undefined ) {
69
+ return undefined ;
70
+ }
71
+
72
+ const key = this . getContextKey ( contextList ) ;
73
+
74
+ // If this list of contexts hasn't been queried before that set the context to the default.
75
+ if ( ! this . _projectContextMap . has ( key ) ) {
76
+ this . _projectContextMap . set ( key , contextList . _vs_projectContexts [ contextList . _vs_defaultIndex ] ) ;
77
+ }
78
+
79
+ return this . _projectContextMap . get ( key ) ;
80
+ }
81
+
82
+ private getContextKey ( contextList : VSProjectContextList ) : string {
83
+ return contextList . _vs_projectContexts
84
+ . map ( ( context ) => context . _vs_label )
85
+ . sort ( )
86
+ . join ( ';' ) ;
87
+ }
88
+
89
+ public setActiveFileContext ( contextList : VSProjectContextList , context : VSProjectContext ) : void {
90
+ const textEditor = vscode . window . activeTextEditor ;
91
+ const uri = textEditor ?. document ?. uri ;
92
+ const languageId = textEditor ?. document ?. languageId ;
93
+ if ( ! uri || languageId !== 'csharp' ) {
94
+ return ;
95
+ }
96
+
97
+ const key = this . getContextKey ( contextList ) ;
98
+ this . _projectContextMap . set ( key , context ) ;
99
+
100
+ this . _contextChangeEmitter . fire ( { languageId, uri, context, isVerified : true , hasAdditionalContexts : true } ) ;
101
+ }
102
+
53
103
public async refresh ( ) {
54
104
const textEditor = vscode . window . activeTextEditor ;
55
105
const languageId = textEditor ?. document ?. languageId ;
@@ -83,19 +133,32 @@ export class ProjectContextService {
83
133
}
84
134
85
135
if ( ! this . _languageServer . isRunning ( ) ) {
86
- this . _contextChangeEmitter . fire ( { languageId, uri, context : this . _emptyProjectContext , isVerified : false } ) ;
136
+ this . _contextChangeEmitter . fire ( {
137
+ languageId,
138
+ uri,
139
+ context : this . _emptyProjectContext ,
140
+ isVerified : false ,
141
+ hasAdditionalContexts : false ,
142
+ } ) ;
87
143
return ;
88
144
}
89
145
90
146
const contextList = await this . getProjectContexts ( uri , this . _source . token ) ;
91
147
if ( ! contextList ) {
92
- this . _contextChangeEmitter . fire ( { languageId, uri, context : this . _emptyProjectContext , isVerified : false } ) ;
148
+ this . _contextChangeEmitter . fire ( {
149
+ languageId,
150
+ uri,
151
+ context : this . _emptyProjectContext ,
152
+ isVerified : false ,
153
+ hasAdditionalContexts : false ,
154
+ } ) ;
93
155
return ;
94
156
}
95
157
96
- const context = contextList . _vs_projectContexts [ contextList . _vs_defaultIndex ] ;
158
+ const context = await this . getDocumentContext ( uri , contextList ) ;
97
159
const isVerified = ! context . _vs_is_miscellaneous || isVerifyPass ;
98
- this . _contextChangeEmitter . fire ( { languageId, uri, context, isVerified } ) ;
160
+ const hasAdditionalContexts = contextList . _vs_projectContexts . length > 1 ;
161
+ this . _contextChangeEmitter . fire ( { languageId, uri, context, isVerified, hasAdditionalContexts } ) ;
99
162
100
163
if ( context . _vs_is_miscellaneous && ! isVerifyPass ) {
101
164
// Request the active project context be refreshed but delay the request to give
@@ -114,11 +177,11 @@ export class ProjectContextService {
114
177
}
115
178
}
116
179
117
- private async getProjectContexts (
118
- uri : vscode . Uri ,
180
+ public async getProjectContexts (
181
+ uri : string | vscode . Uri ,
119
182
token : vscode . CancellationToken
120
183
) : Promise < VSProjectContextList | undefined > {
121
- const uriString = UriConverter . serialize ( uri ) ;
184
+ const uriString = uri instanceof vscode . Uri ? UriConverter . serialize ( uri ) : uri ;
122
185
const textDocument = TextDocumentIdentifier . create ( uriString ) ;
123
186
124
187
try {
0 commit comments