Working version

This commit is contained in:
Ryan Cavanaugh
2016-09-19 16:47:15 -07:00
parent 55f6d4f90d
commit 2612a74f63
6 changed files with 78 additions and 2 deletions

View File

@@ -363,6 +363,10 @@ namespace ts.server {
this.printProjects();
}
private onTypeRootFileChanged(project: ConfiguredProject, fileName: string) {
this.onSourceFileInDirectoryChangedForConfiguredProject(project, fileName);
}
/**
* This is the callback function when a watched directory has added or removed source code files.
* @param project the project that associates with this directory watcher
@@ -389,17 +393,29 @@ namespace ts.server {
const newRootFiles = projectOptions.files.map((f => this.getCanonicalFileName(f)));
const currentRootFiles = project.getRootFiles().map((f => this.getCanonicalFileName(f)));
const lastUpdateTypesRoot: number = Math.max.apply(Math, project.getEffectiveTypeRoots().map(root => {
this.logger.info('Compute for ' + root);
if (this.host.directoryExists(root)) {
return +this.host.getModifiedTime(root);
}
return 0;
}));
this.logger.info('Last type roots update = ' + lastUpdateTypesRoot + ', last was ' + project.lastUpdatedTypesRootTime);
// We check if the project file list has changed. If so, we update the project.
if (!arrayIsEqualTo(currentRootFiles.sort(), newRootFiles.sort())) {
if (!arrayIsEqualTo(currentRootFiles.sort(), newRootFiles.sort()) || (lastUpdateTypesRoot > project.lastUpdatedTypesRootTime)) {
// For configured projects, the change is made outside the tsconfig file, and
// it is not likely to affect the project for other files opened by the client. We can
// just update the current project.
this.logger.info('Updating configured project');
this.updateConfiguredProject(project);
// Call refreshInferredProjects to clean up inferred projects we may have
// created for the new files
this.refreshInferredProjects();
project.lastUpdatedTypesRootTime = lastUpdateTypesRoot;
}
}
@@ -771,13 +787,14 @@ namespace ts.server {
this.watchConfigDirectoryForProject(project, projectOptions);
}
project.watchWildcards((project, path) => this.onSourceFileInDirectoryChangedForConfiguredProject(project, path));
project.watchTypeRoots((project, path) => this.onTypeRootFileChanged(project, path));
this.configuredProjects.push(project);
return project;
}
private watchConfigDirectoryForProject(project: ConfiguredProject, options: ProjectOptions): void {
if (!options.configHasFilesProperty) {
if (!options.configHasFilesProperty || (options.compilerOptions.types === undefined)) {
project.watchConfigDirectory((project, path) => this.onSourceFileInDirectoryChangedForConfiguredProject(project, path));
}
}

View File

@@ -145,6 +145,17 @@ namespace ts.server {
return this.project.getRootFilesLSHost();
}
getTypeRootsVersion() {
const roots = ts.getEffectiveTypeRoots(this.project.getCompilerOptions(), this);
if (roots && roots.length > 0) {
return Math.max.apply(Math, roots.map(root => {
return +this.host.getModifiedTime(root);
}));
} else {
return 0;
}
}
getScriptKind(fileName: string) {
const info = this.project.getScriptInfoLSHost(fileName);
return info && info.scriptKind;

View File

@@ -569,9 +569,11 @@ namespace ts.server {
private projectFileWatcher: FileWatcher;
private directoryWatcher: FileWatcher;
private directoriesWatchedForWildcards: Map<FileWatcher>;
private typeRootsWatchers: FileWatcher[];
/** Used for configured projects which may have multiple open roots */
openRefCount = 0;
lastUpdatedTypesRootTime = 0;
constructor(readonly configFileName: NormalizedPath,
projectService: ProjectService,
@@ -608,6 +610,19 @@ namespace ts.server {
this.projectFileWatcher = this.projectService.host.watchFile(this.configFileName, _ => callback(this));
}
watchTypeRoots(callback: (project: ConfiguredProject, path: string) => void) {
const roots = ts.getEffectiveTypeRoots(this.getCompilerOptions(), this.projectService.host);
this.projectService.logger.info(`Add type roots watchers for: ${roots}`);
const watchers: FileWatcher[] = [];
if (roots) {
for (const root of roots) {
this.projectService.logger.info(`Add type root watcher for: ${root}`);
watchers.push(this.projectService.host.watchDirectory(root, path => callback(this, path), true));
}
}
this.typeRootsWatchers = watchers;
}
watchConfigDirectory(callback: (project: ConfiguredProject, path: string) => void) {
if (this.directoryWatcher) {
return;
@@ -651,6 +666,13 @@ namespace ts.server {
this.projectFileWatcher.close();
}
if (this.typeRootsWatchers) {
for (const watcher of this.typeRootsWatchers) {
watcher.close();
}
this.typeRootsWatchers = undefined;
}
for (const id in this.directoriesWatchedForWildcards) {
this.directoriesWatchedForWildcards[id].close();
}
@@ -667,6 +689,10 @@ namespace ts.server {
this.openRefCount--;
return this.openRefCount;
}
getEffectiveTypeRoots() {
return ts.getEffectiveTypeRoots(this.getCompilerOptions(), this.projectService.host);
}
}
export class ExternalProject extends Project {

View File

@@ -216,6 +216,10 @@ namespace ts.server {
* true if config file explicitly listed files
**/
configHasFilesProperty?: boolean;
/**
* true if config file explicitly listed type names
**/
configHasTypesProperty?: boolean;
/**
* these fields can be present in the project file
**/

View File

@@ -1185,6 +1185,11 @@ namespace ts {
readFile?(path: string, encoding?: string): string;
fileExists?(path: string): boolean;
/*
* LS host can optionally implement these methods to support automatic updating when new type libraries are installed
*/
getTypeRootsVersion?(): number;
/*
* LS host can optionally implement this method if it wants to be completely in charge of module name resolution.
* if implementation is omitted then language service will use built-in module resolution logic and get answers to
@@ -3099,6 +3104,7 @@ namespace ts {
let ruleProvider: formatting.RulesProvider;
let program: Program;
let lastProjectVersion: string;
let lastTypesRootVersion = 0;
const useCaseSensitivefileNames = host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames();
const cancellationToken = new CancellationTokenObject(host.getCancellationToken && host.getCancellationToken());
@@ -3215,6 +3221,13 @@ namespace ts {
};
}
const typeRootsVersion = host.getTypeRootsVersion ? host.getTypeRootsVersion() : 0;
if (lastTypesRootVersion !== typeRootsVersion) {
log('TypeRoots version has changed; provide new program');
program = undefined;
lastTypesRootVersion = typeRootsVersion;
}
const documentRegistryBucketKey = documentRegistry.getKeyForCompilationSettings(newSettings);
const newProgram = createProgram(hostCache.getRootFileNames(), newSettings, compilerHost, program);

View File

@@ -67,6 +67,7 @@ namespace ts {
getProjectVersion?(): string;
useCaseSensitiveFileNames?(): boolean;
getTypeRootsVersion?(): number;
readDirectory(rootDir: string, extension: string, basePaths?: string, excludeEx?: string, includeFileEx?: string, includeDirEx?: string, depth?: number): string;
readFile(path: string, encoding?: string): string;
fileExists(path: string): boolean;
@@ -358,6 +359,10 @@ namespace ts {
return this.shimHost.getProjectVersion();
}
public getTypeRootsVersion(): number {
return this.shimHost.getTypeRootsVersion();
}
public useCaseSensitiveFileNames(): boolean {
return this.shimHost.useCaseSensitiveFileNames ? this.shimHost.useCaseSensitiveFileNames() : false;
}