@@ -12,7 +12,6 @@ import * as lsp from 'vscode-languageserver';
1212import { tsCompletionEntryToLspCompletionItem } from './completion' ;
1313import { tsDiagnosticToLspDiagnostic } from './diagnostic' ;
1414import { Logger } from './logger' ;
15- import { ProjectService } from './project_service' ;
1615import { projectLoadingNotification } from './protocol' ;
1716import { ServerHost } from './server_host' ;
1817import { filePathToUri , lspPositionToTsPosition , lspRangeToTsPositions , tsTextSpanToLspRange , uriToFilePath } from './utils' ;
@@ -37,15 +36,19 @@ const EMPTY_RANGE = lsp.Range.create(0, 0, 0, 0);
3736 */
3837export class Session {
3938 private readonly connection : lsp . IConnection ;
40- private readonly projectService : ProjectService ;
39+ private readonly projectService : ts . server . ProjectService ;
4140 private diagnosticsTimeout : NodeJS . Timeout | null = null ;
4241 private isProjectLoading = false ;
4342
4443 constructor ( options : SessionOptions ) {
4544 // Create a connection for the server. The connection uses Node's IPC as a transport.
4645 this . connection = lsp . createConnection ( ) ;
4746 this . addProtocolHandlers ( this . connection ) ;
48- this . projectService = new ProjectService ( {
47+ this . projectService = this . createProjectService ( options ) ;
48+ }
49+
50+ private createProjectService ( options : SessionOptions ) : ts . server . ProjectService {
51+ const projSvc = new ts . server . ProjectService ( {
4952 host : options . host ,
5053 logger : options . logger ,
5154 cancellationToken : ts . server . nullCancellationToken ,
@@ -63,6 +66,26 @@ export class Session {
6366 pluginProbeLocations : [ options . ngProbeLocation ] ,
6467 allowLocalPluginLoads : false , // do not load plugins from tsconfig.json
6568 } ) ;
69+
70+ projSvc . setHostConfiguration ( {
71+ formatOptions : projSvc . getHostFormatCodeOptions ( ) ,
72+ extraFileExtensions : [
73+ {
74+ extension : '.html' ,
75+ isMixedContent : false ,
76+ scriptKind : ts . ScriptKind . External ,
77+ } ,
78+ ] ,
79+ } ) ;
80+
81+ projSvc . configurePlugin ( {
82+ pluginName : '@angular/language-service' ,
83+ configuration : {
84+ angularOnly : true ,
85+ } ,
86+ } ) ;
87+
88+ return projSvc ;
6689 }
6790
6891 private addProtocolHandlers ( conn : lsp . IConnection ) {
@@ -142,7 +165,7 @@ export class Session {
142165 continue ;
143166 }
144167
145- const ngLS = this . projectService . getDefaultLanguageService ( scriptInfo ) ;
168+ const ngLS = this . getDefaultLanguageService ( scriptInfo ) ;
146169 if ( ! ngLS ) {
147170 continue ;
148171 }
@@ -157,6 +180,53 @@ export class Session {
157180 }
158181 }
159182
183+ /**
184+ * Return the default project for the specified `scriptInfo` if it is already
185+ * a configured project. If not, attempt to find a relevant config file and
186+ * make that project its default. This method is to ensure HTML files always
187+ * belong to a configured project instead of the default behavior of being in
188+ * an inferred project.
189+ * @param scriptInfo
190+ */
191+ getDefaultProjectForScriptInfo ( scriptInfo : ts . server . ScriptInfo ) : ts . server . Project | undefined {
192+ let project = this . projectService . getDefaultProjectForFile (
193+ scriptInfo . fileName ,
194+ // ensureProject tries to find a default project for the scriptInfo if
195+ // it does not already have one. It is not needed here because we are
196+ // going to assign it a project below if it does not have one.
197+ false // ensureProject
198+ ) ;
199+
200+ // TODO: verify that HTML files are attached to Inferred project by default.
201+ // If they are already part of a ConfiguredProject then the following is
202+ // not needed.
203+ if ( ! project || project . projectKind !== ts . server . ProjectKind . Configured ) {
204+ const { configFileName} = this . projectService . openClientFile ( scriptInfo . fileName ) ;
205+ if ( ! configFileName ) {
206+ // Failed to find a config file. There is nothing we could do.
207+ return ;
208+ }
209+ project = this . projectService . findProject ( configFileName ) ;
210+ if ( ! project ) {
211+ return ;
212+ }
213+ scriptInfo . detachAllProjects ( ) ;
214+ scriptInfo . attachToProject ( project ) ;
215+ }
216+
217+ return project ;
218+ }
219+
220+ /**
221+ * Returns a language service for a default project created for the specified `scriptInfo`. If the
222+ * project does not support a language service, nothing is returned.
223+ */
224+ getDefaultLanguageService ( scriptInfo : ts . server . ScriptInfo ) : ts . LanguageService | undefined {
225+ const project = this . getDefaultProjectForScriptInfo ( scriptInfo ) ;
226+ if ( ! project ?. languageServiceEnabled ) return ;
227+ return project . getLanguageService ( ) ;
228+ }
229+
160230 private onInitialize ( params : lsp . InitializeParams ) : lsp . InitializeResult {
161231 return {
162232 capabilities : {
@@ -245,7 +315,7 @@ export class Session {
245315 }
246316 }
247317
248- const project = this . projectService . getDefaultProjectForScriptInfo ( scriptInfo ) ;
318+ const project = this . getDefaultProjectForScriptInfo ( scriptInfo ) ;
249319 if ( ! project || ! project . languageServiceEnabled ) {
250320 return ;
251321 }
@@ -276,7 +346,7 @@ export class Session {
276346 }
277347
278348 const { fileName} = scriptInfo ;
279- const langSvc = this . projectService . getDefaultLanguageService ( scriptInfo ) ;
349+ const langSvc = this . getDefaultLanguageService ( scriptInfo ) ;
280350 if ( ! langSvc ) {
281351 return ;
282352 }
@@ -322,7 +392,7 @@ export class Session {
322392 if ( ! scriptInfo ) {
323393 return ;
324394 }
325- const langSvc = this . projectService . getDefaultLanguageService ( scriptInfo ) ;
395+ const langSvc = this . getDefaultLanguageService ( scriptInfo ) ;
326396 if ( ! langSvc ) {
327397 return ;
328398 }
@@ -366,7 +436,7 @@ export class Session {
366436 return ;
367437 }
368438 const { fileName} = scriptInfo ;
369- const langSvc = this . projectService . getDefaultLanguageService ( scriptInfo ) ;
439+ const langSvc = this . getDefaultLanguageService ( scriptInfo ) ;
370440 if ( ! langSvc ) {
371441 return ;
372442 }
0 commit comments