Skip to content

Commit d64f248

Browse files
committed
Update to respond to PR feedback
1 parent 82e9a75 commit d64f248

File tree

5 files changed

+57
-65
lines changed

5 files changed

+57
-65
lines changed

src/compiler/core.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2988,7 +2988,7 @@ namespace ts {
29882988

29892989
/** Remove the *first* occurrence of `item` from the array. */
29902990
export function unorderedRemoveItem<T>(array: T[], item: T) {
2991-
unorderedRemoveFirstItemWhere(array, element => element === item);
2991+
return unorderedRemoveFirstItemWhere(array, element => element === item);
29922992
}
29932993

29942994
/** Remove the *first* element satisfying `predicate`. */

src/compiler/resolutionCache.ts

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ namespace ts {
1010

1111
invalidateResolutionOfFile(filePath: Path): void;
1212
removeResolutionsOfFile(filePath: Path): void;
13-
setFilesWithInvalidatedNonRelativeUnresolvedImports(filesWithUnresolvedImports: Map<any>): void;
13+
setFilesWithInvalidatedNonRelativeUnresolvedImports(filesWithUnresolvedImports: Map<ReadonlyArray<string>>): void;
1414
createHasInvalidatedResolution(forceAllFilesAsInvalidated?: boolean): HasInvalidatedResolution;
1515

1616
startCachingPerDirectoryResolution(): void;
@@ -75,7 +75,7 @@ namespace ts {
7575
export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootDirForResolution: string, logChangesWhenResolvingModule: boolean): ResolutionCache {
7676
let filesWithChangedSetOfUnresolvedImports: Path[] | undefined;
7777
let filesWithInvalidatedResolutions: Map<true> | undefined;
78-
let filesWithInvalidatedNonRelativeUnresolvedImports: Map<any> | undefined;
78+
let filesWithInvalidatedNonRelativeUnresolvedImports: Map<ReadonlyArray<string>> | undefined;
7979
let allFilesHaveInvalidatedResolution = false;
8080

8181
const getCurrentDirectory = memoize(() => resolutionHost.getCurrentDirectory());
@@ -168,6 +168,16 @@ namespace ts {
168168
return collected;
169169
}
170170

171+
function isFileWithInvalidatedNonRelativeUnresolvedImports(path: Path) {
172+
if (!filesWithInvalidatedNonRelativeUnresolvedImports) {
173+
return false;
174+
}
175+
176+
// Invalidated if file has unresolved imports
177+
const value = filesWithInvalidatedNonRelativeUnresolvedImports.get(path);
178+
return value && !!value.length;
179+
}
180+
171181
function createHasInvalidatedResolution(forceAllFilesAsInvalidated?: boolean): HasInvalidatedResolution {
172182
if (allFilesHaveInvalidatedResolution || forceAllFilesAsInvalidated) {
173183
// Any file asked would have invalidated resolution
@@ -177,7 +187,7 @@ namespace ts {
177187
const collected = filesWithInvalidatedResolutions;
178188
filesWithInvalidatedResolutions = undefined;
179189
return path => (collected && collected.has(path)) ||
180-
(filesWithInvalidatedNonRelativeUnresolvedImports && filesWithInvalidatedNonRelativeUnresolvedImports.has(path));
190+
isFileWithInvalidatedNonRelativeUnresolvedImports(path);
181191
}
182192

183193
function clearPerDirectoryResolutions() {
@@ -242,7 +252,7 @@ namespace ts {
242252

243253
const resolvedModules: R[] = [];
244254
const compilerOptions = resolutionHost.getCompilationSettings();
245-
const hasInvalidatedNonRelativeUnresolvedImport = logChanges && filesWithInvalidatedNonRelativeUnresolvedImports && filesWithInvalidatedNonRelativeUnresolvedImports.has(path);
255+
const hasInvalidatedNonRelativeUnresolvedImport = logChanges && isFileWithInvalidatedNonRelativeUnresolvedImports(path);
246256
const seenNamesInFile = createMap<true>();
247257
for (const name of names) {
248258
let resolution = resolutionsInFile.get(name);
@@ -584,7 +594,7 @@ namespace ts {
584594
);
585595
}
586596

587-
function setFilesWithInvalidatedNonRelativeUnresolvedImports(filesMap: Map<any>) {
597+
function setFilesWithInvalidatedNonRelativeUnresolvedImports(filesMap: Map<ReadonlyArray<string>>) {
588598
Debug.assert(filesWithInvalidatedNonRelativeUnresolvedImports === filesMap || filesWithInvalidatedNonRelativeUnresolvedImports === undefined);
589599
filesWithInvalidatedNonRelativeUnresolvedImports = filesMap;
590600
}

src/server/project.ts

Lines changed: 34 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -96,15 +96,10 @@ namespace ts.server {
9696
*/
9797
cachedUnresolvedImportsPerFile = createMap<ReadonlyArray<string>>();
9898

99-
/**
100-
* This is the set that has entry to true if file doesnt contain any unresolved import
101-
*/
102-
private filesWithNoUnresolvedImports = createMap<true>();
103-
10499
/*@internal*/
105100
lastCachedUnresolvedImportsList: SortedReadonlyArray<string>;
106101
/*@internal*/
107-
hasMoreOrLessScriptInfos = false;
102+
private hasMoreOrLessFiles = false;
108103

109104
private lastFileExceededProgramSize: string | undefined;
110105

@@ -136,10 +131,10 @@ namespace ts.server {
136131
*/
137132
private lastReportedVersion = 0;
138133
/**
139-
* Current project structure version.
134+
* Current project's program version. (incremented everytime new program is created that is not complete reuse from the old one)
140135
* This property is changed in 'updateGraph' based on the set of files in program
141136
*/
142-
private projectStructureVersion = 0;
137+
private projectProgramVersion = 0;
143138
/**
144139
* Current version of the project state. It is changed when:
145140
* - new root file was added/removed
@@ -566,7 +561,6 @@ namespace ts.server {
566561
this.resolutionCache.clear();
567562
this.resolutionCache = undefined;
568563
this.cachedUnresolvedImportsPerFile = undefined;
569-
this.filesWithNoUnresolvedImports = undefined;
570564
this.directoryStructureHost = undefined;
571565

572566
// Clean up file watchers waiting for missing files
@@ -727,7 +721,6 @@ namespace ts.server {
727721
else {
728722
this.resolutionCache.invalidateResolutionOfFile(info.path);
729723
}
730-
this.filesWithNoUnresolvedImports.delete(info.path);
731724
this.cachedUnresolvedImportsPerFile.delete(info.path);
732725

733726
if (detachFromProject) {
@@ -749,19 +742,11 @@ namespace ts.server {
749742
}
750743

751744
/* @internal */
752-
private extractUnresolvedImportsFromSourceFile(file: SourceFile, result: string[] | undefined, ambientModules: string[]): string[] | undefined {
753-
// No unresolve imports in this file
754-
if (this.filesWithNoUnresolvedImports.has(file.path)) {
755-
return result;
756-
}
757-
745+
private extractUnresolvedImportsFromSourceFile(file: SourceFile, ambientModules: string[]): ReadonlyArray<string> {
758746
const cached = this.cachedUnresolvedImportsPerFile.get(file.path);
759747
if (cached) {
760-
// found cached result - use it and return
761-
for (const f of cached) {
762-
(result || (result = [])).push(f);
763-
}
764-
return result;
748+
// found cached result, return
749+
return cached;
765750
}
766751
let unresolvedImports: string[] | undefined;
767752
if (file.resolvedModules) {
@@ -779,40 +764,39 @@ namespace ts.server {
779764
trimmed = trimmed.substr(0, i);
780765
}
781766
(unresolvedImports || (unresolvedImports = [])).push(trimmed);
782-
(result || (result = [])).push(trimmed);
783767
}
784768
});
785769
}
786-
if (unresolvedImports) {
787-
this.cachedUnresolvedImportsPerFile.set(file.path, unresolvedImports);
788-
}
789-
else {
790-
this.filesWithNoUnresolvedImports.set(file.path, true);
791-
}
792-
return result;
770+
771+
this.cachedUnresolvedImportsPerFile.set(file.path, unresolvedImports || emptyArray);
772+
return unresolvedImports || emptyArray;
793773

794774
function isAmbientlyDeclaredModule(name: string) {
795775
return ambientModules.some(m => m === name);
796776
}
797777
}
798778

779+
/* @internal */
780+
setHasMoreOrLessFiles() {
781+
this.hasMoreOrLessFiles = true;
782+
}
783+
799784
/**
800785
* Updates set of files that contribute to this project
801786
* @returns: true if set of files in the project stays the same and false - otherwise.
802787
*/
803788
updateGraph(): boolean {
804789
this.resolutionCache.startRecordingFilesWithChangedResolutions();
805790

806-
const hasChanges = this.updateGraphWorker();
807-
const hasMoreOrLessScriptInfos = this.hasMoreOrLessScriptInfos;
808-
this.hasMoreOrLessScriptInfos = false;
791+
const hasNewProgram = this.updateGraphWorker();
792+
const hasMoreOrLessFiles = this.hasMoreOrLessFiles;
793+
this.hasMoreOrLessFiles = false;
809794

810795
const changedFiles: ReadonlyArray<Path> = this.resolutionCache.finishRecordingFilesWithChangedResolutions() || emptyArray;
811796

812797
for (const file of changedFiles) {
813798
// delete cached information for changed files
814799
this.cachedUnresolvedImportsPerFile.delete(file);
815-
this.filesWithNoUnresolvedImports.delete(file);
816800
}
817801

818802
// update builder only if language service is enabled
@@ -824,25 +808,28 @@ namespace ts.server {
824808
// 3. new files were added/removed, but compilation settings stays the same - collect unresolved imports for all new/modified files
825809
// (can reuse cached imports for files that were not changed)
826810
// 4. compilation settings were changed in the way that might affect module resolution - drop all caches and collect all data from the scratch
827-
if (hasChanges || changedFiles.length) {
811+
if (hasNewProgram || changedFiles.length) {
828812
let result: string[] | undefined;
829813
const ambientModules = this.program.getTypeChecker().getAmbientModules().map(mod => stripQuotes(mod.getName()));
830814
for (const sourceFile of this.program.getSourceFiles()) {
831-
result = this.extractUnresolvedImportsFromSourceFile(sourceFile, result, ambientModules);
815+
const unResolved = this.extractUnresolvedImportsFromSourceFile(sourceFile, ambientModules);
816+
if (unResolved !== emptyArray) {
817+
(result || (result = [])).push(...unResolved);
818+
}
832819
}
833820
this.lastCachedUnresolvedImportsList = result ? toDeduplicatedSortedArray(result) : emptyArray;
834821
}
835822

836-
this.projectService.typingsCache.enqueueInstallTypingsForProject(this, this.lastCachedUnresolvedImportsList, hasMoreOrLessScriptInfos);
823+
this.projectService.typingsCache.enqueueInstallTypingsForProject(this, this.lastCachedUnresolvedImportsList, hasMoreOrLessFiles);
837824
}
838825
else {
839826
this.lastCachedUnresolvedImportsList = undefined;
840827
}
841828

842-
if (hasChanges) {
843-
this.projectStructureVersion++;
829+
if (hasNewProgram) {
830+
this.projectProgramVersion++;
844831
}
845-
return !hasChanges;
832+
return !hasNewProgram;
846833
}
847834

848835
/*@internal*/
@@ -878,9 +865,9 @@ namespace ts.server {
878865
// bump up the version if
879866
// - oldProgram is not set - this is a first time updateGraph is called
880867
// - newProgram is different from the old program and structure of the old program was not reused.
881-
const hasChanges = this.program && (!oldProgram || (this.program !== oldProgram && !(oldProgram.structureIsReused & StructureIsReused.Completely)));
868+
const hasNewProgram = this.program && (!oldProgram || (this.program !== oldProgram && !(oldProgram.structureIsReused & StructureIsReused.Completely)));
882869
this.hasChangedAutomaticTypeDirectiveNames = false;
883-
if (hasChanges) {
870+
if (hasNewProgram) {
884871
if (oldProgram) {
885872
for (const f of oldProgram.getSourceFiles()) {
886873
if (this.program.getSourceFileByPath(f.path)) {
@@ -918,8 +905,8 @@ namespace ts.server {
918905
removed => this.detachScriptInfoFromProject(removed)
919906
);
920907
const elapsed = timestamp() - start;
921-
this.writeLog(`Finishing updateGraphWorker: Project: ${this.getProjectName()} Version: ${this.getProjectVersion()} structureChanged: ${hasChanges} Elapsed: ${elapsed}ms`);
922-
return hasChanges;
908+
this.writeLog(`Finishing updateGraphWorker: Project: ${this.getProjectName()} Version: ${this.getProjectVersion()} structureChanged: ${hasNewProgram} Elapsed: ${elapsed}ms`);
909+
return hasNewProgram;
923910
}
924911

925912
private detachScriptInfoFromProject(uncheckedFileName: string) {
@@ -993,7 +980,6 @@ namespace ts.server {
993980
if (changesAffectModuleResolution(oldOptions, compilerOptions)) {
994981
// reset cached unresolved imports if changes in compiler options affected module resolution
995982
this.cachedUnresolvedImportsPerFile.clear();
996-
this.filesWithNoUnresolvedImports.clear();
997983
this.lastCachedUnresolvedImportsList = undefined;
998984
this.resolutionCache.clear();
999985
}
@@ -1007,7 +993,7 @@ namespace ts.server {
1007993

1008994
const info: protocol.ProjectVersionInfo = {
1009995
projectName: this.getProjectName(),
1010-
version: this.projectStructureVersion,
996+
version: this.projectProgramVersion,
1011997
isInferred: this.projectKind === ProjectKind.Inferred,
1012998
options: this.getCompilationSettings(),
1013999
languageServiceDisabled: !this.languageServiceEnabled,
@@ -1018,7 +1004,7 @@ namespace ts.server {
10181004
// check if requested version is the same that we have reported last time
10191005
if (this.lastReportedFileNames && lastKnownVersion === this.lastReportedVersion) {
10201006
// if current structure version is the same - return info without any changes
1021-
if (this.projectStructureVersion === this.lastReportedVersion && !updatedFileNames) {
1007+
if (this.projectProgramVersion === this.lastReportedVersion && !updatedFileNames) {
10221008
return { info, projectErrors: this.getGlobalProjectErrors() };
10231009
}
10241010
// compute and return the difference
@@ -1041,7 +1027,7 @@ namespace ts.server {
10411027
}
10421028
});
10431029
this.lastReportedFileNames = currentFiles;
1044-
this.lastReportedVersion = this.projectStructureVersion;
1030+
this.lastReportedVersion = this.projectProgramVersion;
10451031
return { info, changes: { added, removed, updated }, projectErrors: this.getGlobalProjectErrors() };
10461032
}
10471033
else {
@@ -1050,7 +1036,7 @@ namespace ts.server {
10501036
const externalFiles = this.getExternalFiles().map(f => toNormalizedPath(f));
10511037
const allFiles = projectFileNames.concat(externalFiles);
10521038
this.lastReportedFileNames = arrayToSet(allFiles);
1053-
this.lastReportedVersion = this.projectStructureVersion;
1039+
this.lastReportedVersion = this.projectProgramVersion;
10541040
return { info, files: allFiles, projectErrors: this.getGlobalProjectErrors() };
10551041
}
10561042
}

src/server/scriptInfo.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ namespace ts.server {
304304
const isNew = !this.isAttached(project);
305305
if (isNew) {
306306
this.containingProjects.push(project);
307-
project.hasMoreOrLessScriptInfos = true;
307+
project.setHasMoreOrLessFiles();
308308
if (!project.getCompilerOptions().preserveSymlinks) {
309309
this.ensureRealPath();
310310
}
@@ -329,23 +329,23 @@ namespace ts.server {
329329
return;
330330
case 1:
331331
if (this.containingProjects[0] === project) {
332-
project.hasMoreOrLessScriptInfos = true;
332+
project.setHasMoreOrLessFiles();
333333
this.containingProjects.pop();
334334
}
335335
break;
336336
case 2:
337337
if (this.containingProjects[0] === project) {
338-
project.hasMoreOrLessScriptInfos = true;
338+
project.setHasMoreOrLessFiles();
339339
this.containingProjects[0] = this.containingProjects.pop();
340340
}
341341
else if (this.containingProjects[1] === project) {
342-
project.hasMoreOrLessScriptInfos = true;
342+
project.setHasMoreOrLessFiles();
343343
this.containingProjects.pop();
344344
}
345345
break;
346346
default:
347347
if (unorderedRemoveItem(this.containingProjects, project)) {
348-
project.hasMoreOrLessScriptInfos = true;
348+
project.setHasMoreOrLessFiles();
349349
}
350350
break;
351351
}

tests/baselines/reference/api/tsserverlibrary.d.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7643,10 +7643,6 @@ declare namespace ts.server {
76437643
private externalFiles;
76447644
private missingFilesMap;
76457645
private plugins;
7646-
/**
7647-
* This is the set that has entry to true if file doesnt contain any unresolved import
7648-
*/
7649-
private filesWithNoUnresolvedImports;
76507646
private lastFileExceededProgramSize;
76517647
protected languageService: LanguageService;
76527648
languageServiceEnabled: boolean;
@@ -7666,10 +7662,10 @@ declare namespace ts.server {
76667662
*/
76677663
private lastReportedVersion;
76687664
/**
7669-
* Current project structure version.
7665+
* Current project's program version. (incremented everytime new program is created that is not complete reuse from the old one)
76707666
* This property is changed in 'updateGraph' based on the set of files in program
76717667
*/
7672-
private projectStructureVersion;
7668+
private projectProgramVersion;
76737669
/**
76747670
* Current version of the project state. It is changed when:
76757671
* - new root file was added/removed

0 commit comments

Comments
 (0)