fix(language-service): Return empty external files during project initialization (#32519)

This PR partially fixes a circular dependency problem whereby the
creation of a project queries Angular plugin for external files, but
the discovery of external files requires root files to be defined in a
Project. The right approach is to return empty array if Project has no
root files.

PR Close #32519
This commit is contained in:
Keen Yee Liau
2019-09-06 14:57:05 -07:00
committed by Matias Niemelä
parent b5eda603a2
commit a65d3fa1de
3 changed files with 44 additions and 8 deletions

View File

@ -6,20 +6,52 @@
* found in the LICENSE file at https://angular.io/license
*/
import * as tss from 'typescript/lib/tsserverlibrary'; // used as type only
import * as tss from 'typescript/lib/tsserverlibrary';
import {createLanguageService} from './language_service';
import {TypeScriptServiceHost} from './typescript_host';
/**
* A note about importing TypeScript module.
* The TypeScript module is supplied by tsserver at runtime to ensure version
* compatibility. In Angular language service, the rollup output is augmented
* with a "banner" shim that overwrites 'typescript' and
* 'typescript/lib/tsserverlibrary' imports with the value supplied by tsserver.
* This means import of either modules will not be "required", but they'll work
* just like regular imports.
*/
const projectHostMap = new WeakMap<tss.server.Project, TypeScriptServiceHost>();
export function getExternalFiles(project: tss.server.Project): string[]|undefined {
const host = projectHostMap.get(project);
if (host) {
host.getAnalyzedModules();
const externalFiles = host.getTemplateReferences();
return externalFiles;
/**
* Return the external templates discovered through processing all NgModules in
* the specified `project`.
* This function is called in a few situations:
* 1. When a ConfiguredProject is created
* https://github.com/microsoft/TypeScript/blob/c26c44d5fceb04ea14da20b6ed23449df777ff34/src/server/editorServices.ts#L1755
* 2. When updateGraph() is called on a Project
* https://github.com/microsoft/TypeScript/blob/c26c44d5fceb04ea14da20b6ed23449df777ff34/src/server/project.ts#L915
* @param project Most likely a ConfiguredProject
*/
export function getExternalFiles(project: tss.server.Project): string[] {
if (!project.hasRoots()) {
// During project initialization where there is no root files yet we should
// not do any work.
return [];
}
const ngLSHost = projectHostMap.get(project);
if (!ngLSHost) {
// Without an Angular host there is no way to get template references.
return [];
}
ngLSHost.getAnalyzedModules();
const templates = ngLSHost.getTemplateReferences();
const logger = project.projectService.logger;
if (logger.hasLevel(tss.server.LogLevel.verbose)) {
// Log external files to help debugging.
logger.info(`External files in ${project.projectName}: ${JSON.stringify(templates)}`);
}
return templates;
}
export function create(info: tss.server.PluginCreateInfo): tss.LanguageService {