@@ -13,7 +13,7 @@ import * as lsp from 'vscode-languageclient/node';
13
13
14
14
import { ProjectLoadingFinish , ProjectLoadingStart , SuggestIvyLanguageService , SuggestIvyLanguageServiceParams , SuggestStrictMode , SuggestStrictModeParams } from '../common/notifications' ;
15
15
import { NgccProgress , NgccProgressToken , NgccProgressType } from '../common/progress' ;
16
- import { GetTcbRequest } from '../common/requests' ;
16
+ import { GetTcbRequest , IsInAngularProject } from '../common/requests' ;
17
17
18
18
import { isInsideComponentDecorator , isInsideInlineTemplateRegion } from './embedded_support' ;
19
19
import { ProgressReporter } from './progress-reporter' ;
@@ -30,6 +30,9 @@ export class AngularLanguageClient implements vscode.Disposable {
30
30
private readonly outputChannel : vscode . OutputChannel ;
31
31
private readonly clientOptions : lsp . LanguageClientOptions ;
32
32
private readonly name = 'Angular Language Service' ;
33
+ private readonly virtualDocumentContents = new Map < string , string > ( ) ;
34
+ /** A map that indicates whether Angular could be found in the file's project. */
35
+ private readonly fileToIsInAngularProjectMap = new Map < string , boolean > ( ) ;
33
36
34
37
constructor ( private readonly context : vscode . ExtensionContext ) {
35
38
this . outputChannel = vscode . window . createOutputChannel ( this . name ) ;
@@ -55,36 +58,71 @@ export class AngularLanguageClient implements vscode.Disposable {
55
58
provideDefinition : async (
56
59
document : vscode . TextDocument , position : vscode . Position ,
57
60
token : vscode . CancellationToken , next : lsp . ProvideDefinitionSignature ) => {
58
- if ( isInsideComponentDecorator ( document , position ) ) {
61
+ if ( await this . isInAngularProject ( document ) &&
62
+ isInsideComponentDecorator ( document , position ) ) {
59
63
return next ( document , position , token ) ;
60
64
}
61
65
} ,
62
66
provideTypeDefinition : async (
63
67
document : vscode . TextDocument , position : vscode . Position ,
64
68
token : vscode . CancellationToken , next ) => {
65
- if ( isInsideInlineTemplateRegion ( document , position ) ) {
69
+ if ( await this . isInAngularProject ( document ) &&
70
+ isInsideInlineTemplateRegion ( document , position ) ) {
66
71
return next ( document , position , token ) ;
67
72
}
68
73
} ,
69
74
provideHover : async (
70
75
document : vscode . TextDocument , position : vscode . Position ,
71
76
token : vscode . CancellationToken , next : lsp . ProvideHoverSignature ) => {
72
- if ( isInsideInlineTemplateRegion ( document , position ) ) {
73
- return next ( document , position , token ) ;
77
+ if ( ! ( await this . isInAngularProject ( document ) ) ||
78
+ ! isInsideInlineTemplateRegion ( document , position ) ) {
79
+ return ;
74
80
}
81
+ return next ( document , position , token ) ;
75
82
} ,
76
83
provideCompletionItem : async (
77
84
document : vscode . TextDocument , position : vscode . Position ,
78
85
context : vscode . CompletionContext , token : vscode . CancellationToken ,
79
86
next : lsp . ProvideCompletionItemsSignature ) => {
80
- if ( isInsideInlineTemplateRegion ( document , position ) ) {
81
- return next ( document , position , context , token ) ;
87
+ // If not in inline template, do not perform request forwarding
88
+ if ( ! ( await this . isInAngularProject ( document ) ) ||
89
+ ! isInsideInlineTemplateRegion ( document , position ) ) {
90
+ return ;
82
91
}
92
+ return next ( document , position , context , token ) ;
83
93
}
84
94
}
85
95
} ;
86
96
}
87
97
98
+ private async isInAngularProject ( doc : vscode . TextDocument ) : Promise < boolean > {
99
+ if ( this . client === null ) {
100
+ return false ;
101
+ }
102
+ const uri = doc . uri . toString ( ) ;
103
+ if ( this . fileToIsInAngularProjectMap . has ( uri ) ) {
104
+ return this . fileToIsInAngularProjectMap . get ( uri ) ! ;
105
+ }
106
+
107
+ try {
108
+ const response = await this . client . sendRequest ( IsInAngularProject , {
109
+ textDocument : this . client . code2ProtocolConverter . asTextDocumentIdentifier ( doc ) ,
110
+ } ) ;
111
+ this . fileToIsInAngularProjectMap . set ( uri , response ) ;
112
+ return response ;
113
+ } catch {
114
+ return false ;
115
+ }
116
+ }
117
+
118
+ private createVirtualHtmlDoc ( document : vscode . TextDocument ) : vscode . Uri {
119
+ const originalUri = document . uri . toString ( ) ;
120
+ const vdocUri = vscode . Uri . file ( encodeURIComponent ( originalUri ) + '.html' )
121
+ . with ( { scheme : 'angular-embedded-content' , authority : 'html' } ) ;
122
+ this . virtualDocumentContents . set ( vdocUri . toString ( ) , document . getText ( ) ) ;
123
+ return vdocUri ;
124
+ }
125
+
88
126
/**
89
127
* Spin up the language server in a separate process and establish a connection.
90
128
*/
@@ -171,7 +209,8 @@ export class AngularLanguageClient implements vscode.Disposable {
171
209
}
172
210
173
211
function registerNotificationHandlers ( client : lsp . LanguageClient ) : vscode . Disposable {
174
- const disposable1 = client . onNotification ( ProjectLoadingStart , ( ) => {
212
+ const disposables : vscode . Disposable [ ] = [ ] ;
213
+ disposables . push ( client . onNotification ( ProjectLoadingStart , ( ) => {
175
214
vscode . window . withProgress (
176
215
{
177
216
location : vscode . ProgressLocation . Window ,
@@ -181,27 +220,26 @@ function registerNotificationHandlers(client: lsp.LanguageClient): vscode.Dispos
181
220
client . onNotification ( ProjectLoadingFinish , resolve ) ;
182
221
} ) ,
183
222
) ;
184
- } ) ;
223
+ } ) ) ;
185
224
186
- const disposable2 =
187
- client . onNotification ( SuggestStrictMode , async ( params : SuggestStrictModeParams ) => {
188
- const openTsConfig = 'Open tsconfig.json' ;
189
- // Markdown is not generally supported in `showInformationMessage()`,
190
- // but links are supported. See
191
- // https://github.com/microsoft/vscode/issues/20595#issuecomment-281099832
192
- const selection = await vscode . window . showInformationMessage (
193
- 'Some language features are not available. To access all features, enable ' +
194
- '[strictTemplates](https://angular.io/guide/angular-compiler-options#stricttemplates) in ' +
195
- '[angularCompilerOptions](https://angular.io/guide/angular-compiler-options).' ,
196
- openTsConfig ,
197
- ) ;
198
- if ( selection === openTsConfig ) {
199
- const document = await vscode . workspace . openTextDocument ( params . configFilePath ) ;
200
- vscode . window . showTextDocument ( document ) ;
201
- }
202
- } ) ;
225
+ disposables . push ( client . onNotification ( SuggestStrictMode , async ( params : SuggestStrictModeParams ) => {
226
+ const openTsConfig = 'Open tsconfig.json' ;
227
+ // Markdown is not generally supported in `showInformationMessage()`,
228
+ // but links are supported. See
229
+ // https://github.com/microsoft/vscode/issues/20595#issuecomment-281099832
230
+ const selection = await vscode . window . showInformationMessage (
231
+ 'Some language features are not available. To access all features, enable ' +
232
+ '[strictTemplates](https://angular.io/guide/angular-compiler-options#stricttemplates) in ' +
233
+ '[angularCompilerOptions](https://angular.io/guide/angular-compiler-options).' ,
234
+ openTsConfig ,
235
+ ) ;
236
+ if ( selection === openTsConfig ) {
237
+ const document = await vscode . workspace . openTextDocument ( params . configFilePath ) ;
238
+ vscode . window . showTextDocument ( document ) ;
239
+ }
240
+ } ) ) ;
203
241
204
- const disposable3 = client . onNotification (
242
+ disposables . push ( client . onNotification (
205
243
SuggestIvyLanguageService , async ( params : SuggestIvyLanguageServiceParams ) => {
206
244
const config = vscode . workspace . getConfiguration ( ) ;
207
245
if ( config . get ( 'angular.enable-experimental-ivy-prompt' ) === false ) {
@@ -221,9 +259,9 @@ function registerNotificationHandlers(client: lsp.LanguageClient): vscode.Dispos
221
259
config . update (
222
260
'angular.enable-experimental-ivy-prompt' , false , vscode . ConfigurationTarget . Global ) ;
223
261
}
224
- } ) ;
262
+ } ) ) ;
225
263
226
- return vscode . Disposable . from ( disposable1 , disposable2 , disposable3 ) ;
264
+ return vscode . Disposable . from ( ... disposables ) ;
227
265
}
228
266
229
267
function registerProgressHandlers ( client : lsp . LanguageClient ) {
0 commit comments