@@ -10,12 +10,14 @@ import { TextDocumentIdentifier } from 'vscode-languageserver-protocol';
1010import { UriConverter } from '../uriConverter' ;
1111import { LanguageServerEvents } from '../languageServerEvents' ;
1212import { ServerState } from '../serverStateChange' ;
13+ import { CancellationToken } from 'vscode-languageclient/node' ;
1314
1415export interface ProjectContextChangeEvent {
1516 languageId : string ;
1617 uri : vscode . Uri ;
1718 context : VSProjectContext ;
1819 isVerified : boolean ;
20+ hasAdditionalContexts : boolean ;
1921}
2022
2123const VerificationDelay = 2 * 1000 ;
@@ -24,6 +26,7 @@ let _verifyTimeout: NodeJS.Timeout | undefined;
2426let _documentUriToVerify : vscode . Uri | undefined ;
2527
2628export class ProjectContextService {
29+ private readonly _projectContextMap : Map < string , VSProjectContext > = new Map ( ) ;
2730 private readonly _contextChangeEmitter = new vscode . EventEmitter < ProjectContextChangeEvent > ( ) ;
2831 private _source = new vscode . CancellationTokenSource ( ) ;
2932 private readonly _emptyProjectContext : VSProjectContext = {
@@ -50,6 +53,53 @@ export class ProjectContextService {
5053 return this . _contextChangeEmitter . event ;
5154 }
5255
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+
53103 public async refresh ( ) {
54104 const textEditor = vscode . window . activeTextEditor ;
55105 const languageId = textEditor ?. document ?. languageId ;
@@ -83,19 +133,32 @@ export class ProjectContextService {
83133 }
84134
85135 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+ } ) ;
87143 return ;
88144 }
89145
90146 const contextList = await this . getProjectContexts ( uri , this . _source . token ) ;
91147 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+ } ) ;
93155 return ;
94156 }
95157
96- const context = contextList . _vs_projectContexts [ contextList . _vs_defaultIndex ] ;
158+ const context = await this . getDocumentContext ( uri , contextList ) ;
97159 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 } ) ;
99162
100163 if ( context . _vs_is_miscellaneous && ! isVerifyPass ) {
101164 // Request the active project context be refreshed but delay the request to give
@@ -114,11 +177,11 @@ export class ProjectContextService {
114177 }
115178 }
116179
117- private async getProjectContexts (
118- uri : vscode . Uri ,
180+ public async getProjectContexts (
181+ uri : string | vscode . Uri ,
119182 token : vscode . CancellationToken
120183 ) : Promise < VSProjectContextList | undefined > {
121- const uriString = UriConverter . serialize ( uri ) ;
184+ const uriString = uri instanceof vscode . Uri ? UriConverter . serialize ( uri ) : uri ;
122185 const textDocument = TextDocumentIdentifier . create ( uriString ) ;
123186
124187 try {
0 commit comments