mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-07 17:29:36 -05:00
Working version
This commit is contained in:
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
**/
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user