@@ -13,7 +13,7 @@ import * as lsp from 'vscode-languageclient/node';
1313
1414import { ProjectLoadingFinish , ProjectLoadingStart , SuggestIvyLanguageService , SuggestIvyLanguageServiceParams , SuggestStrictMode , SuggestStrictModeParams } from '../common/notifications' ;
1515import { NgccProgress , NgccProgressToken , NgccProgressType } from '../common/progress' ;
16- import { GetTcbRequest } from '../common/requests' ;
16+ import { GetTcbRequest , IsInAngularProject } from '../common/requests' ;
1717
1818import { isInsideComponentDecorator , isInsideInlineTemplateRegion } from './embedded_support' ;
1919import { ProgressReporter } from './progress-reporter' ;
@@ -30,6 +30,9 @@ export class AngularLanguageClient implements vscode.Disposable {
3030 private readonly outputChannel : vscode . OutputChannel ;
3131 private readonly clientOptions : lsp . LanguageClientOptions ;
3232 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 > ( ) ;
3336
3437 constructor ( private readonly context : vscode . ExtensionContext ) {
3538 this . outputChannel = vscode . window . createOutputChannel ( this . name ) ;
@@ -55,36 +58,71 @@ export class AngularLanguageClient implements vscode.Disposable {
5558 provideDefinition : async (
5659 document : vscode . TextDocument , position : vscode . Position ,
5760 token : vscode . CancellationToken , next : lsp . ProvideDefinitionSignature ) => {
58- if ( isInsideComponentDecorator ( document , position ) ) {
61+ if ( await this . isInAngularProject ( document ) &&
62+ isInsideComponentDecorator ( document , position ) ) {
5963 return next ( document , position , token ) ;
6064 }
6165 } ,
6266 provideTypeDefinition : async (
6367 document : vscode . TextDocument , position : vscode . Position ,
6468 token : vscode . CancellationToken , next ) => {
65- if ( isInsideInlineTemplateRegion ( document , position ) ) {
69+ if ( await this . isInAngularProject ( document ) &&
70+ isInsideInlineTemplateRegion ( document , position ) ) {
6671 return next ( document , position , token ) ;
6772 }
6873 } ,
6974 provideHover : async (
7075 document : vscode . TextDocument , position : vscode . Position ,
7176 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 ;
7480 }
81+ return next ( document , position , token ) ;
7582 } ,
7683 provideCompletionItem : async (
7784 document : vscode . TextDocument , position : vscode . Position ,
7885 context : vscode . CompletionContext , token : vscode . CancellationToken ,
7986 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 ;
8291 }
92+ return next ( document , position , context , token ) ;
8393 }
8494 }
8595 } ;
8696 }
8797
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+
88126 /**
89127 * Spin up the language server in a separate process and establish a connection.
90128 */
@@ -171,7 +209,8 @@ export class AngularLanguageClient implements vscode.Disposable {
171209}
172210
173211function registerNotificationHandlers ( client : lsp . LanguageClient ) : vscode . Disposable {
174- const disposable1 = client . onNotification ( ProjectLoadingStart , ( ) => {
212+ const disposables : vscode . Disposable [ ] = [ ] ;
213+ disposables . push ( client . onNotification ( ProjectLoadingStart , ( ) => {
175214 vscode . window . withProgress (
176215 {
177216 location : vscode . ProgressLocation . Window ,
@@ -181,27 +220,26 @@ function registerNotificationHandlers(client: lsp.LanguageClient): vscode.Dispos
181220 client . onNotification ( ProjectLoadingFinish , resolve ) ;
182221 } ) ,
183222 ) ;
184- } ) ;
223+ } ) ) ;
185224
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+ } ) ) ;
203241
204- const disposable3 = client . onNotification (
242+ disposables . push ( client . onNotification (
205243 SuggestIvyLanguageService , async ( params : SuggestIvyLanguageServiceParams ) => {
206244 const config = vscode . workspace . getConfiguration ( ) ;
207245 if ( config . get ( 'angular.enable-experimental-ivy-prompt' ) === false ) {
@@ -221,9 +259,9 @@ function registerNotificationHandlers(client: lsp.LanguageClient): vscode.Dispos
221259 config . update (
222260 'angular.enable-experimental-ivy-prompt' , false , vscode . ConfigurationTarget . Global ) ;
223261 }
224- } ) ;
262+ } ) ) ;
225263
226- return vscode . Disposable . from ( disposable1 , disposable2 , disposable3 ) ;
264+ return vscode . Disposable . from ( ... disposables ) ;
227265}
228266
229267function registerProgressHandlers ( client : lsp . LanguageClient ) {
0 commit comments