PR feedback

This commit is contained in:
Sheetal Nandi
2017-09-26 13:34:56 -07:00
parent 38f3a2b700
commit 68d360585a
20 changed files with 472 additions and 431 deletions

View File

@@ -349,7 +349,7 @@ namespace ts.server {
private readonly projectToSizeMap: Map<number> = createMap<number>();
/**
* This is a map of config file paths existance that doesnt need query to disk
* - The entry can be present because there is inferred project that needs to watch addition of config file to folder
* - The entry can be present because there is inferred project that needs to watch addition of config file to directory
* In this case the exists could be true/false based on config file is present or not
* - Or it is present if we have configured project open with config file at that location
* In this case the exists property is always true
@@ -753,15 +753,15 @@ namespace ts.server {
return this.watchDirectory(
this.host,
directory,
fileOrFolder => {
const fileOrFolderPath = this.toPath(fileOrFolder);
project.getCachedDirectoryStructureHost().addOrDeleteFileOrFolder(fileOrFolder, fileOrFolderPath);
fileOrDirectory => {
const fileOrDirectoryPath = this.toPath(fileOrDirectory);
project.getCachedDirectoryStructureHost().addOrDeleteFileOrDirectory(fileOrDirectory, fileOrDirectoryPath);
const configFilename = project.getConfigFilePath();
// If the the added or created file or folder is not supported file name, ignore the file
// If the the added or created file or directory is not supported file name, ignore the file
// But when watched directory is added/removed, we need to reload the file list
if (fileOrFolderPath !== directory && !isSupportedSourceFileName(fileOrFolder, project.getCompilationSettings(), this.hostConfiguration.extraFileExtensions)) {
this.logger.info(`Project: ${configFilename} Detected file add/remove of non supported extension: ${fileOrFolder}`);
if (fileOrDirectoryPath !== directory && !isSupportedSourceFileName(fileOrDirectory, project.getCompilationSettings(), this.hostConfiguration.extraFileExtensions)) {
this.logger.info(`Project: ${configFilename} Detected file add/remove of non supported extension: ${fileOrDirectory}`);
return;
}
@@ -833,7 +833,7 @@ namespace ts.server {
switch (project.projectKind) {
case ProjectKind.External:
unorderedRemoveItem(this.externalProjects, <ExternalProject>project);
this.projectToSizeMap.delete((project as ExternalProject).externalProjectName);
this.projectToSizeMap.delete(project.getProjectName());
break;
case ProjectKind.Configured:
this.configuredProjects.delete((<ConfiguredProject>project).canonicalConfigFilePath);
@@ -852,7 +852,7 @@ namespace ts.server {
const project = this.getOrCreateInferredProjectForProjectRootPathIfEnabled(info, projectRootPath) ||
this.getOrCreateSingleInferredProjectIfEnabled() ||
this.createInferredProject();
this.createInferredProject(getDirectoryPath(info.path));
project.addRoot(info);
project.updateGraph();
@@ -1374,7 +1374,7 @@ namespace ts.server {
this.addFilesToNonInferredProjectAndUpdateGraph(project, files, externalFilePropertyReader, typeAcquisition);
this.externalProjects.push(project);
this.sendProjectTelemetry(project.externalProjectName, project);
this.sendProjectTelemetry(projectFileName, project);
return project;
}
@@ -1461,7 +1461,7 @@ namespace ts.server {
this.addFilesToNonInferredProjectAndUpdateGraph(project, filesToAdd, fileNamePropertyReader, projectOptions.typeAcquisition);
this.configuredProjects.set(project.canonicalConfigFilePath, project);
this.setConfigFileExistenceByNewConfiguredProject(project);
this.sendProjectTelemetry(project.getConfigFilePath(), project, projectOptions);
this.sendProjectTelemetry(configFileName, project, projectOptions);
return project;
}
@@ -1584,7 +1584,7 @@ namespace ts.server {
return project;
}
}
return this.createInferredProject(/*isSingleInferredProject*/ false, projectRootPath);
return this.createInferredProject(projectRootPath, /*isSingleInferredProject*/ false, projectRootPath);
}
// we don't have an explicit root path, so we should try to find an inferred project
@@ -1621,12 +1621,12 @@ namespace ts.server {
return this.inferredProjects[0];
}
return this.createInferredProject(/*isSingleInferredProject*/ true);
return this.createInferredProject(/*rootDirectoryForResolution*/ undefined, /*isSingleInferredProject*/ true);
}
private createInferredProject(isSingleInferredProject?: boolean, projectRootPath?: string): InferredProject {
private createInferredProject(rootDirectoryForResolution: string | undefined, isSingleInferredProject?: boolean, projectRootPath?: string): InferredProject {
const compilerOptions = projectRootPath && this.compilerOptionsForInferredProjectsPerProjectRoot.get(projectRootPath) || this.compilerOptionsForInferredProjects;
const project = new InferredProject(this, this.documentRegistry, compilerOptions, projectRootPath);
const project = new InferredProject(this, this.documentRegistry, compilerOptions, projectRootPath, rootDirectoryForResolution);
if (isSingleInferredProject) {
this.inferredProjects.unshift(project);
}
@@ -1669,10 +1669,12 @@ namespace ts.server {
}
}
/*@internal*/
getOrCreateScriptInfoNotOpenedByClientForNormalizedPath(fileName: NormalizedPath, scriptKind?: ScriptKind, hasMixedContent?: boolean, hostToQueryFileExistsOn?: DirectoryStructureHost) {
return this.getOrCreateScriptInfoForNormalizedPath(fileName, /*openedByClient*/ false, /*fileContent*/ undefined, scriptKind, hasMixedContent, hostToQueryFileExistsOn);
}
/*@internal*/
getOrCreateScriptInfoOpenedByClientForNormalizedPath(fileName: NormalizedPath, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean, hostToQueryFileExistsOn?: DirectoryStructureHost) {
return this.getOrCreateScriptInfoForNormalizedPath(fileName, /*openedByClient*/ true, fileContent, scriptKind, hasMixedContent, hostToQueryFileExistsOn);
}

View File

@@ -162,7 +162,8 @@ namespace ts.server {
*/
private projectStateVersion = 0;
private changedAutomaticTypeDirectiveNames = false;
/*@internal*/
hasChangedAutomaticTypeDirectiveNames = false;
private typingFiles: SortedReadonlyArray<string>;
@@ -201,7 +202,8 @@ namespace ts.server {
languageServiceEnabled: boolean,
private compilerOptions: CompilerOptions,
public compileOnSaveEnabled: boolean,
/*@internal*/public directoryStructureHost: DirectoryStructureHost) {
/*@internal*/public directoryStructureHost: DirectoryStructureHost,
rootDirectoryForResolution: string | undefined) {
if (!this.compilerOptions) {
this.compilerOptions = getDefaultCompilerOptions();
@@ -224,7 +226,7 @@ namespace ts.server {
}
this.languageService = createLanguageService(this, this.documentRegistry);
this.resolutionCache = createResolutionCache(this);
this.resolutionCache = createResolutionCache(this, rootDirectoryForResolution);
if (!languageServiceEnabled) {
this.disableLanguageService();
}
@@ -244,29 +246,26 @@ namespace ts.server {
}
getScriptFileNames() {
const result: string[] = [];
if (this.rootFiles) {
this.rootFilesMap.forEach((value, _path) => {
const f: ScriptInfo = isScriptInfo(value) && value;
if (this.languageServiceEnabled || (f && f.isScriptOpen())) {
// if language service is disabled - process only files that are open
result.push(f ? f.fileName : value as NormalizedPath);
}
});
if (this.typingFiles) {
for (const f of this.typingFiles) {
result.push(f);
}
}
if (!this.rootFiles) {
return ts.emptyArray;
}
return result;
let result: string[] | undefined;
this.rootFilesMap.forEach(value => {
if (this.languageServiceEnabled || (isScriptInfo(value) && value.isScriptOpen())) {
// if language service is disabled - process only files that are open
(result || (result = [])).push(isScriptInfo(value) ? value.fileName : value);
}
});
return addRange(result, this.typingFiles) || ts.emptyArray;
}
private getScriptInfoLSHost(fileName: string) {
private getOrCreateScriptInfoAndAttachToProject(fileName: string) {
const scriptInfo = this.projectService.getOrCreateScriptInfoNotOpenedByClient(fileName, this.directoryStructureHost);
if (scriptInfo) {
const existingValue = this.rootFilesMap.get(scriptInfo.path);
if (existingValue !== undefined && existingValue !== scriptInfo) {
if (existingValue !== scriptInfo && existingValue !== undefined) {
// This was missing path earlier but now the file exists. Update the root
this.rootFiles.push(scriptInfo);
this.rootFilesMap.set(scriptInfo.path, scriptInfo);
@@ -277,17 +276,17 @@ namespace ts.server {
}
getScriptKind(fileName: string) {
const info = this.getScriptInfoLSHost(fileName);
const info = this.getOrCreateScriptInfoAndAttachToProject(fileName);
return info && info.scriptKind;
}
getScriptVersion(filename: string) {
const info = this.getScriptInfoLSHost(filename);
const info = this.getOrCreateScriptInfoAndAttachToProject(filename);
return info && info.getLatestVersion();
}
getScriptSnapshot(filename: string): IScriptSnapshot {
const scriptInfo = this.getScriptInfoLSHost(filename);
const scriptInfo = this.getOrCreateScriptInfoAndAttachToProject(filename);
if (scriptInfo) {
return scriptInfo.getSnapshot();
}
@@ -377,15 +376,10 @@ namespace ts.server {
/*@internal*/
onChangedAutomaticTypeDirectiveNames() {
this.changedAutomaticTypeDirectiveNames = true;
this.hasChangedAutomaticTypeDirectiveNames = true;
this.projectService.delayUpdateProjectGraphAndInferredProjectsRefresh(this);
}
/*@internal*/
hasChangedAutomaticTypeDirectiveNames() {
return this.changedAutomaticTypeDirectiveNames;
}
/*@internal*/
getGlobalCache() {
return this.getTypeAcquisition().enable ? this.projectService.typingsInstaller.globalTypingsCacheLocation : undefined;
@@ -802,7 +796,7 @@ namespace ts.server {
// - oldProgram is not set - this is a first time updateGraph is called
// - newProgram is different from the old program and structure of the old program was not reused.
const hasChanges = !oldProgram || (this.program !== oldProgram && !(oldProgram.structureIsReused & StructureIsReused.Completely));
this.changedAutomaticTypeDirectiveNames = false;
this.hasChangedAutomaticTypeDirectiveNames = false;
if (hasChanges) {
if (oldProgram) {
for (const f of oldProgram.getSourceFiles()) {
@@ -1035,7 +1029,12 @@ namespace ts.server {
super.setCompilerOptions(newOptions);
}
constructor(projectService: ProjectService, documentRegistry: DocumentRegistry, compilerOptions: CompilerOptions, public readonly projectRootPath?: string | undefined) {
constructor(
projectService: ProjectService,
documentRegistry: DocumentRegistry,
compilerOptions: CompilerOptions,
public readonly projectRootPath: string | undefined,
rootDirectoryForResolution: string | undefined) {
super(InferredProject.newName(),
ProjectKind.Inferred,
projectService,
@@ -1044,7 +1043,8 @@ namespace ts.server {
/*languageServiceEnabled*/ true,
compilerOptions,
/*compileOnSaveEnabled*/ false,
projectService.host);
projectService.host,
rootDirectoryForResolution);
}
addRoot(info: ScriptInfo) {
@@ -1053,13 +1053,6 @@ namespace ts.server {
this.toggleJsInferredProject(/*isJsInferredProject*/ true);
}
super.addRoot(info);
// For first root set the resolution cache root dir
if (this.getRootFiles.length === 1) {
const rootDirPath = this.getProjectRootPath();
if (rootDirPath) {
this.resolutionCache.setRootDirectory(rootDirPath);
}
}
}
removeRoot(info: ScriptInfo) {
@@ -1081,11 +1074,9 @@ namespace ts.server {
}
getProjectRootPath() {
// Single inferred project does not have a project root.
if (this.projectService.useSingleInferredProject) {
return undefined;
}
return this.projectRootPath || getDirectoryPath(this.getRootFiles()[0]);
return this.projectRootPath ||
// Single inferred project does not have a project root.
!this.projectService.useSingleInferredProject && getDirectoryPath(this.getRootFiles()[0]);
}
close() {
@@ -1135,10 +1126,18 @@ namespace ts.server {
languageServiceEnabled: boolean,
public compileOnSaveEnabled: boolean,
cachedDirectoryStructureHost: CachedDirectoryStructureHost) {
super(configFileName, ProjectKind.Configured, projectService, documentRegistry, hasExplicitListOfFiles, languageServiceEnabled, compilerOptions, compileOnSaveEnabled, cachedDirectoryStructureHost);
super(configFileName,
ProjectKind.Configured,
projectService,
documentRegistry,
hasExplicitListOfFiles,
languageServiceEnabled,
compilerOptions,
compileOnSaveEnabled,
cachedDirectoryStructureHost,
getDirectoryPath(configFileName));
this.canonicalConfigFilePath = asNormalizedPath(projectService.toCanonicalFileName(configFileName));
this.enablePlugins();
this.resolutionCache.setRootDirectory(getDirectoryPath(configFileName));
}
/**
@@ -1370,8 +1369,15 @@ namespace ts.server {
languageServiceEnabled: boolean,
public compileOnSaveEnabled: boolean,
private readonly projectFilePath?: string) {
super(externalProjectName, ProjectKind.External, projectService, documentRegistry, /*hasExplicitListOfFiles*/ true, languageServiceEnabled, compilerOptions, compileOnSaveEnabled, projectService.host);
this.resolutionCache.setRootDirectory(this.getProjectRootPath());
super(externalProjectName,
ProjectKind.External,
projectService,
documentRegistry,
/*hasExplicitListOfFiles*/ true,
languageServiceEnabled, compilerOptions,
compileOnSaveEnabled,
projectService.host,
getDirectoryPath(projectFilePath || normalizeSlashes(externalProjectName)));
}
getExcludedFiles() {

View File

@@ -4,17 +4,36 @@ namespace ts.server {
/* @internal */
export class TextStorage {
// Generated only on demand and removes the text if any edits
/**
* Generated only on demand (based on edits, or information requested)
* The property text is set to undefined when edits happen on the cache
*/
private svc: ScriptVersionCache | undefined;
private svcVersion = 0;
// Store text when there is no svc or svc has no change, on edit, remove the text
/**
* Stores the text when there are no changes to the script version cache
* The script version cache is generated on demand and text is still retained.
* Only on edits to the script version cache, the text will be set to undefined
*/
private text: string;
/**
* Line map for the text when there is no script version cache present
*/
private lineMap: number[];
private textVersion = 0;
/**
* True if the text is for the file thats open in the editor
*/
public isOpen: boolean;
/**
* True if the text present is the text from the file on the disk
*/
private ownFileText: boolean;
/**
* True when reloading contents of file from the disk is pending
*/
private pendingReloadFromDisk: boolean;
constructor(private readonly host: ServerHost, private readonly fileName: NormalizedPath) {