Skip to content

Commit

Permalink
Add searchPaths option so we know where to look for watchFactory from…
Browse files Browse the repository at this point in the history
… server which follows same locations as other Plugins
  • Loading branch information
sheetalkamat committed Oct 10, 2022
1 parent fc57b16 commit 83822a3
Show file tree
Hide file tree
Showing 28 changed files with 654 additions and 612 deletions.
11 changes: 7 additions & 4 deletions src/compiler/sys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -846,7 +846,7 @@ namespace ts {
/*@internal*/
export function resolveModule<T = {}>(
pluginConfigEntry: PluginImport,
searchPaths: string[],
searchPaths: readonly string[],
host: Pick<System, "require" | "resolvePath">,
log: (message: string) => void,
): ImportPluginResult<T> {
Expand Down Expand Up @@ -945,9 +945,12 @@ namespace ts {
sysLog(`Skipped loading watchFactory ${isString(options.watchFactory) ? options.watchFactory : JSON.stringify(options.watchFactory)} because it can be named with only package name`);
return setUserWatchFactory(options, /*userWatchFactory*/ undefined);
}
const searchPaths = [
combinePaths(system.getExecutingFilePath(), "../../..")
];
const host = options.getHost?.();
const searchPaths = host ?
host.searchPaths :
[
combinePaths(system.getExecutingFilePath(), "../../..")
];
sysLog(`Enabling watchFactory ${isString(options.watchFactory) ? options.watchFactory : JSON.stringify(options.watchFactory)} from candidate paths: ${searchPaths.join(",")}`);
const { resolvedModule, errorLogs, pluginConfigEntry } = resolveModule<UserWatchFactoryModule>(
isString(options.watchFactory) ? { name: options.watchFactory } : options.watchFactory,
Expand Down
5 changes: 5 additions & 0 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6679,6 +6679,10 @@ namespace ts {
watchDirectory?(fileName: string, callback: DirectoryWatcherCallback, recursive: boolean, options: WatchOptions | undefined): FileWatcher;
onConfigurationChanged?(config: any): void;
}
/*@internal*/
export interface WatchOptionsFactoryHost {
searchPaths: readonly string[];
}
export interface WatchOptions {
watchFile?: WatchFileKind;
watchDirectory?: WatchDirectoryKind;
Expand All @@ -6690,6 +6694,7 @@ namespace ts {

// All the internal properties are set as non enumerable and non configurable so that they arenot enumerated when checking if options have changed
/* @internal */ getResolvedWatchFactory?(): UserWatchFactory | undefined;
/* @internal */ getHost?(): WatchOptionsFactoryHost;

[option: string]: CompilerOptionsValue | undefined;
}
Expand Down
50 changes: 41 additions & 9 deletions src/server/editorServices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1311,7 +1311,7 @@ namespace ts.server {
* This is to watch whenever files are added or removed to the wildcard directories
*/
/*@internal*/
private watchWildcardDirectory(directory: Path, flags: WatchDirectoryFlags, configFileName: NormalizedPath, config: ParsedConfig) {
private watchWildcardDirectory(directory: Path, flags: WatchDirectoryFlags, configFileName: NormalizedPath, canonicalConfigFilePath: NormalizedPath, config: ParsedConfig) {
return this.watchFactory.watchDirectory(
directory,
fileOrDirectory => {
Expand Down Expand Up @@ -1370,7 +1370,7 @@ namespace ts.server {
});
},
flags,
this.getWatchOptionsFromProjectWatchOptions(config.parsedCommandLine!.watchOptions),
this.getWatchOptionsFromProjectWatchOptions(config.parsedCommandLine!.watchOptions, canonicalConfigFilePath),
WatchType.WildcardDirectory,
configFileName
);
Expand Down Expand Up @@ -1684,7 +1684,7 @@ namespace ts.server {
configFileName,
(_fileName, eventKind) => this.onConfigFileChanged(canonicalConfigFilePath, eventKind),
PollingInterval.High,
this.getWatchOptionsFromProjectWatchOptions(configFileExistenceInfo?.config?.parsedCommandLine?.watchOptions),
this.getWatchOptionsFromProjectWatchOptions(configFileExistenceInfo?.config?.parsedCommandLine?.watchOptions, canonicalConfigFilePath),
WatchType.ConfigFile,
forProject
);
Expand Down Expand Up @@ -2236,9 +2236,9 @@ namespace ts.server {
// If watch options different than older options when setting for the first time, update the config file watcher
if (!oldCommandLine && !isJsonEqual(
// Old options
this.getWatchOptionsFromProjectWatchOptions(/*projectOptions*/ undefined),
this.getWatchOptionsFromProjectWatchOptions(/*projectOptions*/ undefined, canonicalConfigFilePath),
// New options
this.getWatchOptionsFromProjectWatchOptions(parsedCommandLine.watchOptions)
this.getWatchOptionsFromProjectWatchOptions(parsedCommandLine.watchOptions, canonicalConfigFilePath)
)) {
// Reset the config file watcher
configFileExistenceInfo.watcher?.close();
Expand Down Expand Up @@ -2284,7 +2284,7 @@ namespace ts.server {
config!.watchedDirectories ||= new Map(),
new Map(getEntries(config!.parsedCommandLine!.wildcardDirectories!)),
// Create new directory watcher
(directory, flags) => this.watchWildcardDirectory(directory as Path, flags, configFileName, config!),
(directory, flags) => this.watchWildcardDirectory(directory as Path, flags, configFileName, forProject.canonicalConfigFilePath, config!),
);
}
else {
Expand Down Expand Up @@ -3044,6 +3044,9 @@ namespace ts.server {
if (args.watchOptions) {
const result = convertWatchOptions(args.watchOptions);
this.hostConfiguration.watchOptions = result?.watchOptions;
if (this.hostConfiguration.watchOptions?.watchFactory) {
this.setWatchOptionsFactoryHost(this.hostConfiguration.watchOptions, /*canonicalConfigFilePath*/ undefined);
}
this.projectWatchOptions.clear();
this.logger.info(`Host watch options changed to ${JSON.stringify(this.hostConfiguration.watchOptions)}, it will be take effect for next watches.`);
if (result?.errors?.length) {
Expand All @@ -3059,22 +3062,30 @@ namespace ts.server {
}

/*@internal*/
getWatchOptions(project: Project) {
return this.getWatchOptionsFromProjectWatchOptions(project.getWatchOptions());
getWatchOptions(project: Project): WatchOptions | undefined {
return this.getWatchOptionsFromProjectWatchOptions(project.getWatchOptions(), isConfiguredProject(project) ? project.canonicalConfigFilePath : undefined);
}

/*@internal*/
private getWatchOptionsFromProjectWatchOptions(projectOptions: WatchOptions | undefined) {
private getWatchOptionsFromProjectWatchOptions(projectOptions: WatchOptions | undefined, canonicalConfigFilePath: NormalizedPath | undefined) {
if (!projectOptions) return this.hostConfiguration.watchOptions;
let options = this.projectWatchOptions.get(projectOptions);
if (options) return options;
this.projectWatchOptions.set(projectOptions, options = this.hostConfiguration.watchOptions ?
{ ...this.hostConfiguration.watchOptions, ...projectOptions } :
projectOptions
);
this.setWatchOptionsFactoryHost(options, canonicalConfigFilePath);
return options;
}

/*@internal*/
private setWatchOptionsFactoryHost(options: WatchOptions, canonicalConfigFilePath: NormalizedPath | undefined) {
setWatchOptionInternalProperty(options, "getHost", memoize(() => ({
searchPaths: this.getProjectPluginSearchPaths(canonicalConfigFilePath)
})));
}

/*@internal*/
clearWatchOptionsFromProjectWatchOptions(projectOptions: WatchOptions | undefined) {
if (projectOptions) this.projectWatchOptions.delete(projectOptions);
Expand Down Expand Up @@ -4097,6 +4108,27 @@ namespace ts.server {
return false;
}

/*@internal */
getGlobalPluginSearchPaths() {
// Search any globally-specified probe paths, then our peer node_modules
return [
...this.pluginProbeLocations,
// ../../.. to walk from X/node_modules/typescript/lib/tsserver.js to X/node_modules/
combinePaths(this.getExecutingFilePath(), "../../.."),
];
}

/*@internal*/
getProjectPluginSearchPaths(canonicalConfigFilePath: string | undefined) {
const searchPaths = this.getGlobalPluginSearchPaths();
if (canonicalConfigFilePath && this.allowLocalPluginLoads) {
const local = getDirectoryPath(canonicalConfigFilePath);
this.logger.info(`Local plugin loading enabled; adding ${local} to search paths`);
searchPaths.unshift(local);
}
return searchPaths;
}

/*@internal*/
requestEnablePlugin(project: Project, pluginConfigEntry: PluginImport, searchPaths: string[]) {
if (!this.host.importPlugin && !this.host.require) {
Expand Down
24 changes: 9 additions & 15 deletions src/server/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1604,13 +1604,8 @@ namespace ts.server {
}

/*@internal*/
protected getGlobalPluginSearchPaths() {
// Search any globally-specified probe paths, then our peer node_modules
return [
...this.projectService.pluginProbeLocations,
// ../../.. to walk from X/node_modules/typescript/lib/tsserver.js to X/node_modules/
combinePaths(this.projectService.getExecutingFilePath(), "../../.."),
];
protected getProjectPluginSearchPaths() {
return this.projectService.getProjectPluginSearchPaths(/*canonicalConfigFilePath*/ undefined);
}

protected enableGlobalPlugins(options: CompilerOptions): void {
Expand All @@ -1623,7 +1618,7 @@ namespace ts.server {
}

// Enable global plugins with synthetic configuration entries
const searchPaths = this.getGlobalPluginSearchPaths();
const searchPaths = this.projectService.getGlobalPluginSearchPaths();
for (const globalPluginName of this.projectService.globalPlugins) {
// Skip empty names from odd commandline parses
if (!globalPluginName) continue;
Expand Down Expand Up @@ -2481,6 +2476,11 @@ namespace ts.server {
return this.getCurrentProgram()?.forEachResolvedProjectReference(cb);
}

/*@internal*/
protected getProjectPluginSearchPaths() {
return this.projectService.getProjectPluginSearchPaths(this.canonicalConfigFilePath);
}

/*@internal*/
enablePluginsWithOptions(options: CompilerOptions): void {
this.plugins.length = 0;
Expand All @@ -2491,14 +2491,8 @@ namespace ts.server {
return;
}

const searchPaths = this.getGlobalPluginSearchPaths();
if (this.projectService.allowLocalPluginLoads) {
const local = getDirectoryPath(this.canonicalConfigFilePath);
this.projectService.logger.info(`Local plugin loading enabled; adding ${local} to search paths`);
searchPaths.unshift(local);
}

// Enable tsconfig-specified plugins
const searchPaths = this.getProjectPluginSearchPaths();
if (options.plugins) {
for (const pluginConfigEntry of options.plugins) {
this.enablePlugin(pluginConfigEntry, searchPaths);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ Info 6 [00:00:29.000] Search path: /user/username/projects/myproject
Info 7 [00:00:30.000] For info: /user/username/projects/myproject/a.ts :: Config file name: /user/username/projects/myproject/tsconfig.json
Info 8 [00:00:31.000] Creating configuration project /user/username/projects/myproject/tsconfig.json
Info 9 [00:00:32.000] FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/tsconfig.json 2000 {"watchFactory":{"name":"myplugin","myconfig":"somethingelse"}} Project: /user/username/projects/myproject/tsconfig.json WatchType: Config file
CustomRequire:: Resolving myplugin from /a/lib/tsc.js/../../../node_modules
CustomRequire:: Resolving myplugin from /a/pluginprobe1/node_modules
Require:: Module myplugin created with config: {"name":"myplugin","myconfig":"somethingelse"} and options: {"watchFactory":{"name":"myplugin","myconfig":"somethingelse"}}
Custom watchFile: /user/username/projects/myproject/tsconfig.json 2000 {"watchFactory":{"name":"myplugin","myconfig":"somethingelse"}}
Info 10 [00:00:33.000] Config: /user/username/projects/myproject/tsconfig.json : {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ Info 6 [00:00:29.000] Search path: /user/username/projects/myproject
Info 7 [00:00:30.000] For info: /user/username/projects/myproject/a.ts :: Config file name: /user/username/projects/myproject/tsconfig.json
Info 8 [00:00:31.000] Creating configuration project /user/username/projects/myproject/tsconfig.json
Info 9 [00:00:32.000] FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/tsconfig.json 2000 {"watchFactory":"myplugin"} Project: /user/username/projects/myproject/tsconfig.json WatchType: Config file
CustomRequire:: Resolving myplugin from /a/lib/tsc.js/../../../node_modules
CustomRequire:: Resolving myplugin from /a/pluginprobe1/node_modules
Require:: Module myplugin created with config: {"name":"myplugin"} and options: {"watchFactory":"myplugin"}
Custom watchFile: /user/username/projects/myproject/tsconfig.json 2000 {"watchFactory":"myplugin"}
Info 10 [00:00:33.000] Config: /user/username/projects/myproject/tsconfig.json : {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ Info 6 [00:00:29.000] Search path: /user/username/projects/myproject
Info 7 [00:00:30.000] For info: /user/username/projects/myproject/a.ts :: Config file name: /user/username/projects/myproject/tsconfig.json
Info 8 [00:00:31.000] Creating configuration project /user/username/projects/myproject/tsconfig.json
Info 9 [00:00:32.000] FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/tsconfig.json 2000 {"watchFactory":{"name":"myplugin","myconfig":"somethingelse"}} Project: /user/username/projects/myproject/tsconfig.json WatchType: Config file
CustomRequire:: Resolving myplugin from /a/lib/tsc.js/../../../node_modules
CustomRequire:: Resolving myplugin from /a/pluginprobe1/node_modules
Require:: Module myplugin created with config: {"name":"myplugin","myconfig":"somethingelse"} and options: {"watchFactory":{"name":"myplugin","myconfig":"somethingelse"}}
Custom watchFile: /user/username/projects/myproject/tsconfig.json 2000 {"watchFactory":{"name":"myplugin","myconfig":"somethingelse"}}
Info 10 [00:00:33.000] Config: /user/username/projects/myproject/tsconfig.json : {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ Info 9 [00:00:32.000] Search path: /user/username/projects/myproject
Info 10 [00:00:33.000] For info: /user/username/projects/myproject/a.ts :: Config file name: /user/username/projects/myproject/tsconfig.json
Info 11 [00:00:34.000] Creating configuration project /user/username/projects/myproject/tsconfig.json
Info 12 [00:00:35.000] FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/tsconfig.json 2000 {"watchFactory":{"name":"myplugin","myconfig":"somethingelse"}} Project: /user/username/projects/myproject/tsconfig.json WatchType: Config file
CustomRequire:: Resolving myplugin from /a/lib/tsc.js/../../../node_modules
CustomRequire:: Resolving myplugin from /a/pluginprobe1/node_modules
Require:: Module myplugin created with config: {"name":"myplugin","myconfig":"somethingelse"} and options: {"watchFactory":{"name":"myplugin","myconfig":"somethingelse"}}
Custom watchFile: /user/username/projects/myproject/tsconfig.json 2000 {"watchFactory":{"name":"myplugin","myconfig":"somethingelse"}}
Info 13 [00:00:36.000] Config: /user/username/projects/myproject/tsconfig.json : {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ Info 9 [00:00:32.000] Search path: /user/username/projects/myproject
Info 10 [00:00:33.000] For info: /user/username/projects/myproject/a.ts :: Config file name: /user/username/projects/myproject/tsconfig.json
Info 11 [00:00:34.000] Creating configuration project /user/username/projects/myproject/tsconfig.json
Info 12 [00:00:35.000] FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/tsconfig.json 2000 {"watchFactory":{"name":"myplugin","myconfig":"somethingelse"}} Project: /user/username/projects/myproject/tsconfig.json WatchType: Config file
CustomRequire:: Resolving myplugin from /a/lib/tsc.js/../../../node_modules
CustomRequire:: Resolving myplugin from /a/pluginprobe1/node_modules
Require:: Module myplugin created with config: {"name":"myplugin","myconfig":"somethingelse"} and options: {"watchFactory":{"name":"myplugin","myconfig":"somethingelse"}}
Custom watchFile: /user/username/projects/myproject/tsconfig.json 2000 {"watchFactory":{"name":"myplugin","myconfig":"somethingelse"}}
Info 13 [00:00:36.000] Config: /user/username/projects/myproject/tsconfig.json : {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ Info 9 [00:00:32.000] Search path: /user/username/projects/myproject
Info 10 [00:00:33.000] For info: /user/username/projects/myproject/a.ts :: Config file name: /user/username/projects/myproject/tsconfig.json
Info 11 [00:00:34.000] Creating configuration project /user/username/projects/myproject/tsconfig.json
Info 12 [00:00:35.000] FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/tsconfig.json 2000 {"watchFactory":"myplugin"} Project: /user/username/projects/myproject/tsconfig.json WatchType: Config file
CustomRequire:: Resolving myplugin from /a/lib/tsc.js/../../../node_modules
CustomRequire:: Resolving myplugin from /a/pluginprobe1/node_modules
Require:: Module myplugin created with config: {"name":"myplugin"} and options: {"watchFactory":"myplugin"}
Custom watchFile: /user/username/projects/myproject/tsconfig.json 2000 {"watchFactory":"myplugin"}
Info 13 [00:00:36.000] Config: /user/username/projects/myproject/tsconfig.json : {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ Info 9 [00:00:32.000] Search path: /user/username/projects/myproject
Info 10 [00:00:33.000] For info: /user/username/projects/myproject/a.ts :: Config file name: /user/username/projects/myproject/tsconfig.json
Info 11 [00:00:34.000] Creating configuration project /user/username/projects/myproject/tsconfig.json
Info 12 [00:00:35.000] FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/tsconfig.json 2000 {"watchFactory":"myplugin"} Project: /user/username/projects/myproject/tsconfig.json WatchType: Config file
CustomRequire:: Resolving myplugin from /a/lib/tsc.js/../../../node_modules
CustomRequire:: Resolving myplugin from /a/pluginprobe1/node_modules
Require:: Module myplugin created with config: {"name":"myplugin"} and options: {"watchFactory":"myplugin"}
Custom watchFile: /user/username/projects/myproject/tsconfig.json 2000 {"watchFactory":"myplugin"}
Info 13 [00:00:36.000] Config: /user/username/projects/myproject/tsconfig.json : {
Expand Down
Loading

0 comments on commit 83822a3

Please sign in to comment.