Skip to content

Commit 2612a74

Browse files
committed
Working version
1 parent 55f6d4f commit 2612a74

6 files changed

Lines changed: 78 additions & 2 deletions

File tree

src/server/editorServices.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,10 @@ namespace ts.server {
363363
this.printProjects();
364364
}
365365

366+
private onTypeRootFileChanged(project: ConfiguredProject, fileName: string) {
367+
this.onSourceFileInDirectoryChangedForConfiguredProject(project, fileName);
368+
}
369+
366370
/**
367371
* This is the callback function when a watched directory has added or removed source code files.
368372
* @param project the project that associates with this directory watcher
@@ -389,17 +393,29 @@ namespace ts.server {
389393

390394
const newRootFiles = projectOptions.files.map((f => this.getCanonicalFileName(f)));
391395
const currentRootFiles = project.getRootFiles().map((f => this.getCanonicalFileName(f)));
396+
const lastUpdateTypesRoot: number = Math.max.apply(Math, project.getEffectiveTypeRoots().map(root => {
397+
this.logger.info('Compute for ' + root);
398+
if (this.host.directoryExists(root)) {
399+
return +this.host.getModifiedTime(root);
400+
}
401+
return 0;
402+
}));
403+
this.logger.info('Last type roots update = ' + lastUpdateTypesRoot + ', last was ' + project.lastUpdatedTypesRootTime);
392404

393405
// We check if the project file list has changed. If so, we update the project.
394-
if (!arrayIsEqualTo(currentRootFiles.sort(), newRootFiles.sort())) {
406+
if (!arrayIsEqualTo(currentRootFiles.sort(), newRootFiles.sort()) || (lastUpdateTypesRoot > project.lastUpdatedTypesRootTime)) {
395407
// For configured projects, the change is made outside the tsconfig file, and
396408
// it is not likely to affect the project for other files opened by the client. We can
397409
// just update the current project.
410+
411+
this.logger.info('Updating configured project');
398412
this.updateConfiguredProject(project);
399413

400414
// Call refreshInferredProjects to clean up inferred projects we may have
401415
// created for the new files
402416
this.refreshInferredProjects();
417+
418+
project.lastUpdatedTypesRootTime = lastUpdateTypesRoot;
403419
}
404420
}
405421

@@ -771,13 +787,14 @@ namespace ts.server {
771787
this.watchConfigDirectoryForProject(project, projectOptions);
772788
}
773789
project.watchWildcards((project, path) => this.onSourceFileInDirectoryChangedForConfiguredProject(project, path));
790+
project.watchTypeRoots((project, path) => this.onTypeRootFileChanged(project, path));
774791

775792
this.configuredProjects.push(project);
776793
return project;
777794
}
778795

779796
private watchConfigDirectoryForProject(project: ConfiguredProject, options: ProjectOptions): void {
780-
if (!options.configHasFilesProperty) {
797+
if (!options.configHasFilesProperty || (options.compilerOptions.types === undefined)) {
781798
project.watchConfigDirectory((project, path) => this.onSourceFileInDirectoryChangedForConfiguredProject(project, path));
782799
}
783800
}

src/server/lsHost.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,17 @@ namespace ts.server {
145145
return this.project.getRootFilesLSHost();
146146
}
147147

148+
getTypeRootsVersion() {
149+
const roots = ts.getEffectiveTypeRoots(this.project.getCompilerOptions(), this);
150+
if (roots && roots.length > 0) {
151+
return Math.max.apply(Math, roots.map(root => {
152+
return +this.host.getModifiedTime(root);
153+
}));
154+
} else {
155+
return 0;
156+
}
157+
}
158+
148159
getScriptKind(fileName: string) {
149160
const info = this.project.getScriptInfoLSHost(fileName);
150161
return info && info.scriptKind;

src/server/project.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -569,9 +569,11 @@ namespace ts.server {
569569
private projectFileWatcher: FileWatcher;
570570
private directoryWatcher: FileWatcher;
571571
private directoriesWatchedForWildcards: Map<FileWatcher>;
572+
private typeRootsWatchers: FileWatcher[];
572573

573574
/** Used for configured projects which may have multiple open roots */
574575
openRefCount = 0;
576+
lastUpdatedTypesRootTime = 0;
575577

576578
constructor(readonly configFileName: NormalizedPath,
577579
projectService: ProjectService,
@@ -608,6 +610,19 @@ namespace ts.server {
608610
this.projectFileWatcher = this.projectService.host.watchFile(this.configFileName, _ => callback(this));
609611
}
610612

613+
watchTypeRoots(callback: (project: ConfiguredProject, path: string) => void) {
614+
const roots = ts.getEffectiveTypeRoots(this.getCompilerOptions(), this.projectService.host);
615+
this.projectService.logger.info(`Add type roots watchers for: ${roots}`);
616+
const watchers: FileWatcher[] = [];
617+
if (roots) {
618+
for (const root of roots) {
619+
this.projectService.logger.info(`Add type root watcher for: ${root}`);
620+
watchers.push(this.projectService.host.watchDirectory(root, path => callback(this, path), true));
621+
}
622+
}
623+
this.typeRootsWatchers = watchers;
624+
}
625+
611626
watchConfigDirectory(callback: (project: ConfiguredProject, path: string) => void) {
612627
if (this.directoryWatcher) {
613628
return;
@@ -651,6 +666,13 @@ namespace ts.server {
651666
this.projectFileWatcher.close();
652667
}
653668

669+
if (this.typeRootsWatchers) {
670+
for (const watcher of this.typeRootsWatchers) {
671+
watcher.close();
672+
}
673+
this.typeRootsWatchers = undefined;
674+
}
675+
654676
for (const id in this.directoriesWatchedForWildcards) {
655677
this.directoriesWatchedForWildcards[id].close();
656678
}
@@ -667,6 +689,10 @@ namespace ts.server {
667689
this.openRefCount--;
668690
return this.openRefCount;
669691
}
692+
693+
getEffectiveTypeRoots() {
694+
return ts.getEffectiveTypeRoots(this.getCompilerOptions(), this.projectService.host);
695+
}
670696
}
671697

672698
export class ExternalProject extends Project {

src/server/utilities.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,10 @@ namespace ts.server {
216216
* true if config file explicitly listed files
217217
**/
218218
configHasFilesProperty?: boolean;
219+
/**
220+
* true if config file explicitly listed type names
221+
**/
222+
configHasTypesProperty?: boolean;
219223
/**
220224
* these fields can be present in the project file
221225
**/

src/services/services.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1185,6 +1185,11 @@ namespace ts {
11851185
readFile?(path: string, encoding?: string): string;
11861186
fileExists?(path: string): boolean;
11871187

1188+
/*
1189+
* LS host can optionally implement these methods to support automatic updating when new type libraries are installed
1190+
*/
1191+
getTypeRootsVersion?(): number;
1192+
11881193
/*
11891194
* LS host can optionally implement this method if it wants to be completely in charge of module name resolution.
11901195
* if implementation is omitted then language service will use built-in module resolution logic and get answers to
@@ -3099,6 +3104,7 @@ namespace ts {
30993104
let ruleProvider: formatting.RulesProvider;
31003105
let program: Program;
31013106
let lastProjectVersion: string;
3107+
let lastTypesRootVersion = 0;
31023108

31033109
const useCaseSensitivefileNames = host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames();
31043110
const cancellationToken = new CancellationTokenObject(host.getCancellationToken && host.getCancellationToken());
@@ -3215,6 +3221,13 @@ namespace ts {
32153221
};
32163222
}
32173223

3224+
const typeRootsVersion = host.getTypeRootsVersion ? host.getTypeRootsVersion() : 0;
3225+
if (lastTypesRootVersion !== typeRootsVersion) {
3226+
log('TypeRoots version has changed; provide new program');
3227+
program = undefined;
3228+
lastTypesRootVersion = typeRootsVersion;
3229+
}
3230+
32183231
const documentRegistryBucketKey = documentRegistry.getKeyForCompilationSettings(newSettings);
32193232
const newProgram = createProgram(hostCache.getRootFileNames(), newSettings, compilerHost, program);
32203233

src/services/shims.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ namespace ts {
6767
getProjectVersion?(): string;
6868
useCaseSensitiveFileNames?(): boolean;
6969

70+
getTypeRootsVersion?(): number;
7071
readDirectory(rootDir: string, extension: string, basePaths?: string, excludeEx?: string, includeFileEx?: string, includeDirEx?: string, depth?: number): string;
7172
readFile(path: string, encoding?: string): string;
7273
fileExists(path: string): boolean;
@@ -358,6 +359,10 @@ namespace ts {
358359
return this.shimHost.getProjectVersion();
359360
}
360361

362+
public getTypeRootsVersion(): number {
363+
return this.shimHost.getTypeRootsVersion();
364+
}
365+
361366
public useCaseSensitiveFileNames(): boolean {
362367
return this.shimHost.useCaseSensitiveFileNames ? this.shimHost.useCaseSensitiveFileNames() : false;
363368
}

0 commit comments

Comments
 (0)