Skip to content

Commit 67d6ee5

Browse files
committed
Add searchPaths option so we know where to look for watchFactory from server which follows same locations as other Plugins
1 parent 060eff8 commit 67d6ee5

File tree

28 files changed

+640
-604
lines changed

28 files changed

+640
-604
lines changed

src/compiler/sys.ts

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -841,7 +841,7 @@ namespace ts {
841841
/*@internal*/
842842
export function resolveModule<T = {}>(
843843
pluginConfigEntry: PluginImport,
844-
searchPaths: string[],
844+
searchPaths: readonly string[],
845845
host: Pick<System, "require" | "resolvePath">,
846846
log: (message: string) => void,
847847
): ImportPluginResult<T> {
@@ -865,7 +865,7 @@ namespace ts {
865865
/*@internal*/
866866
export async function importPlugin<T = {}>(
867867
pluginConfigEntry: PluginImport,
868-
searchPaths: string[],
868+
searchPaths: readonly string[],
869869
host: Pick<System, "importPlugin">,
870870
log: (message: string) => void,
871871
): Promise<ImportPluginResult<T>> {
@@ -985,12 +985,16 @@ namespace ts {
985985
options.getResolvedWatchFactory = returnUndefined;
986986
}
987987
else {
988-
const searchPaths = options.configFile ? [
989-
getDirectoryPath(getNormalizedAbsolutePath(options.configFile.fileName, system.getCurrentDirectory())),
990-
combinePaths(system.getExecutingFilePath(), "../../..")
991-
] : [
992-
combinePaths(system.getExecutingFilePath(), "../../..")
993-
];
988+
const searchPaths = options.watchFactorySearchPaths ?
989+
options.watchFactorySearchPaths() :
990+
// Do we allow configFile
991+
// Do we need allowLocalPlugins and pluginProbeLocations for compile time as well?
992+
options.configFile ? [
993+
getDirectoryPath(getNormalizedAbsolutePath(options.configFile.fileName, system.getCurrentDirectory())),
994+
combinePaths(system.getExecutingFilePath(), "../../..")
995+
] : [
996+
combinePaths(system.getExecutingFilePath(), "../../..")
997+
];
994998
sysLog(`Enabling watchFactory ${isString(options.watchFactory) ? options.watchFactory : options.watchFactory.name} from candidate paths: ${searchPaths.join(",")}`);
995999
watchFactory = system.importPlugin ?
9961000
importFactory(options, searchPaths, system) :
@@ -1015,7 +1019,7 @@ namespace ts {
10151019
return resolvedWatchFactory;
10161020
}
10171021

1018-
function importFactory(options: WatchOptions, searchPaths: string[], system: System) {
1022+
function importFactory(options: WatchOptions, searchPaths: readonly string[], system: System) {
10191023
return setGetResolvedWatchFactory(options, {
10201024
pending: importPlugin<UserWatchFactory>(
10211025
isString(options.watchFactory) ? { name: options.watchFactory } : options.watchFactory!,

src/compiler/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6695,6 +6695,7 @@ namespace ts {
66956695
/** configFile is set as non enumerable property so as to avoid checking of json source files */
66966696
/* @internal */ readonly configFile?: TsConfigSourceFile;
66976697
/* @internal */ getResolvedWatchFactory?(): ResolvedWatchFactory | undefined;
6698+
/* @internal */ watchFactorySearchPaths?(): readonly string[];
66986699

66996700
[option: string]: CompilerOptionsValue | TsConfigSourceFile | undefined;
67006701
}

src/server/editorServices.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2237,6 +2237,7 @@ namespace ts.server {
22372237
configFileExistenceInfo.config.watchedDirectoriesStale = true;
22382238
configFileExistenceInfo.config.reloadLevel = undefined;
22392239
}
2240+
if (parsedCommandLine.watchOptions) parsedCommandLine.watchOptions.watchFactorySearchPaths = () => this.getProjectPluginSearchPaths(canonicalConfigFilePath);
22402241

22412242
// If watch options different than older options when setting for the first time, update the config file watcher
22422243
if (!oldCommandLine && !isJsonEqual(
@@ -3049,6 +3050,10 @@ namespace ts.server {
30493050
if (args.watchOptions) {
30503051
const result = convertWatchOptions(args.watchOptions);
30513052
this.hostConfiguration.watchOptions = result?.watchOptions;
3053+
if (this.hostConfiguration.watchOptions?.watchFactory) {
3054+
// Set the watchFactory searchPaths same as global paths
3055+
this.hostConfiguration.watchOptions.watchFactorySearchPaths = () => this.getGlobalPluginSearchPaths();
3056+
}
30523057
this.projectWatchOptions.clear();
30533058
this.logger.info(`Host watch options changed to ${JSON.stringify(this.hostConfiguration.watchOptions)}, it will be take effect for next watches.`);
30543059
if (result?.errors?.length) {
@@ -4106,6 +4111,27 @@ namespace ts.server {
41064111
return false;
41074112
}
41084113

4114+
/*@internal */
4115+
getGlobalPluginSearchPaths() {
4116+
// Search any globally-specified probe paths, then our peer node_modules
4117+
return [
4118+
...this.pluginProbeLocations,
4119+
// ../../.. to walk from X/node_modules/typescript/lib/tsserver.js to X/node_modules/
4120+
combinePaths(this.getExecutingFilePath(), "../../.."),
4121+
];
4122+
}
4123+
4124+
/*@internal*/
4125+
getProjectPluginSearchPaths(canonicalConfigFilePath: string | undefined) {
4126+
const searchPaths = this.getGlobalPluginSearchPaths();
4127+
if (canonicalConfigFilePath && this.allowLocalPluginLoads) {
4128+
const local = getDirectoryPath(canonicalConfigFilePath);
4129+
this.logger.info(`Local plugin loading enabled; adding ${local} to search paths`);
4130+
searchPaths.unshift(local);
4131+
}
4132+
return searchPaths;
4133+
}
4134+
41094135
/*@internal*/
41104136
requestEnablePlugin(project: Project, pluginConfigEntry: PluginImport, searchPaths: string[]) {
41114137
if (!this.host.importPlugin && !this.host.require) {

src/server/project.ts

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1440,6 +1440,9 @@ namespace ts.server {
14401440
/*@internal*/
14411441
setWatchOptions(watchOptions: WatchOptions | undefined) {
14421442
this.watchOptions = watchOptions;
1443+
if (this.watchOptions?.watchFactory) {
1444+
this.watchOptions.watchFactorySearchPaths = () => this.getProjectPluginSearchPaths();
1445+
}
14431446
}
14441447

14451448
/*@internal*/
@@ -1574,13 +1577,8 @@ namespace ts.server {
15741577
}
15751578

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

15861584
protected enableGlobalPlugins(options: CompilerOptions): void {
@@ -1593,7 +1591,7 @@ namespace ts.server {
15931591
}
15941592

15951593
// Enable global plugins with synthetic configuration entries
1596-
const searchPaths = this.getGlobalPluginSearchPaths();
1594+
const searchPaths = this.projectService.getGlobalPluginSearchPaths();
15971595
for (const globalPluginName of this.projectService.globalPlugins) {
15981596
// Skip empty names from odd commandline parses
15991597
if (!globalPluginName) continue;
@@ -2451,6 +2449,11 @@ namespace ts.server {
24512449
return this.getCurrentProgram()?.forEachResolvedProjectReference(cb);
24522450
}
24532451

2452+
/*@internal*/
2453+
protected getProjectPluginSearchPaths() {
2454+
return this.projectService.getProjectPluginSearchPaths(this.canonicalConfigFilePath);
2455+
}
2456+
24542457
/*@internal*/
24552458
enablePluginsWithOptions(options: CompilerOptions): void {
24562459
this.plugins.length = 0;
@@ -2461,14 +2464,8 @@ namespace ts.server {
24612464
return;
24622465
}
24632466

2464-
const searchPaths = this.getGlobalPluginSearchPaths();
2465-
if (this.projectService.allowLocalPluginLoads) {
2466-
const local = getDirectoryPath(this.canonicalConfigFilePath);
2467-
this.projectService.logger.info(`Local plugin loading enabled; adding ${local} to search paths`);
2468-
searchPaths.unshift(local);
2469-
}
2470-
24712467
// Enable tsconfig-specified plugins
2468+
const searchPaths = this.getProjectPluginSearchPaths();
24722469
if (options.plugins) {
24732470
for (const pluginConfigEntry of options.plugins) {
24742471
this.enablePlugin(pluginConfigEntry, searchPaths);

tests/baselines/reference/tsserver/watchEnvironment/watchFactory-as-configuration-of-host-allowLocalPluginLoads-object.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ Info 6 [00:00:29.000] Search path: /user/username/projects/myproject
9494
Info 7 [00:00:30.000] For info: /user/username/projects/myproject/a.ts :: Config file name: /user/username/projects/myproject/tsconfig.json
9595
Info 8 [00:00:31.000] Creating configuration project /user/username/projects/myproject/tsconfig.json
9696
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
97-
CustomRequire:: Resolving myplugin from /a/lib/tsc.js/../../../node_modules
97+
CustomRequire:: Resolving myplugin from /a/pluginprobe1/node_modules
9898
Custom watchFile: /user/username/projects/myproject/tsconfig.json 2000 {"watchFactory":{"name":"myplugin","myconfig":"somethingelse"}}
9999
Info 10 [00:00:33.000] Config: /user/username/projects/myproject/tsconfig.json : {
100100
"rootNames": [

tests/baselines/reference/tsserver/watchEnvironment/watchFactory-as-configuration-of-host-allowLocalPluginLoads.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ Info 6 [00:00:29.000] Search path: /user/username/projects/myproject
9191
Info 7 [00:00:30.000] For info: /user/username/projects/myproject/a.ts :: Config file name: /user/username/projects/myproject/tsconfig.json
9292
Info 8 [00:00:31.000] Creating configuration project /user/username/projects/myproject/tsconfig.json
9393
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
94-
CustomRequire:: Resolving myplugin from /a/lib/tsc.js/../../../node_modules
94+
CustomRequire:: Resolving myplugin from /a/pluginprobe1/node_modules
9595
Custom watchFile: /user/username/projects/myproject/tsconfig.json 2000 {"watchFactory":"myplugin"}
9696
Info 10 [00:00:33.000] Config: /user/username/projects/myproject/tsconfig.json : {
9797
"rootNames": [

tests/baselines/reference/tsserver/watchEnvironment/watchFactory-as-configuration-of-host-object.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ Info 6 [00:00:29.000] Search path: /user/username/projects/myproject
9494
Info 7 [00:00:30.000] For info: /user/username/projects/myproject/a.ts :: Config file name: /user/username/projects/myproject/tsconfig.json
9595
Info 8 [00:00:31.000] Creating configuration project /user/username/projects/myproject/tsconfig.json
9696
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
97-
CustomRequire:: Resolving myplugin from /a/lib/tsc.js/../../../node_modules
97+
CustomRequire:: Resolving myplugin from /a/pluginprobe1/node_modules
9898
Custom watchFile: /user/username/projects/myproject/tsconfig.json 2000 {"watchFactory":{"name":"myplugin","myconfig":"somethingelse"}}
9999
Info 10 [00:00:33.000] Config: /user/username/projects/myproject/tsconfig.json : {
100100
"rootNames": [

tests/baselines/reference/tsserver/watchEnvironment/watchFactory-as-configuration-of-host-with-pluginoverride-allowLocalPluginLoads-object.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ Info 9 [00:00:32.000] Search path: /user/username/projects/myproject
138138
Info 10 [00:00:33.000] For info: /user/username/projects/myproject/a.ts :: Config file name: /user/username/projects/myproject/tsconfig.json
139139
Info 11 [00:00:34.000] Creating configuration project /user/username/projects/myproject/tsconfig.json
140140
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
141-
CustomRequire:: Resolving myplugin from /a/lib/tsc.js/../../../node_modules
141+
CustomRequire:: Resolving myplugin from /a/pluginprobe1/node_modules
142142
Custom watchFile: /user/username/projects/myproject/tsconfig.json 2000 {"watchFactory":{"name":"myplugin","myconfig":"somethingelse"}}
143143
Info 13 [00:00:36.000] Config: /user/username/projects/myproject/tsconfig.json : {
144144
"rootNames": [

tests/baselines/reference/tsserver/watchEnvironment/watchFactory-as-configuration-of-host-with-pluginoverride-allowLocalPluginLoads.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ Info 9 [00:00:32.000] Search path: /user/username/projects/myproject
135135
Info 10 [00:00:33.000] For info: /user/username/projects/myproject/a.ts :: Config file name: /user/username/projects/myproject/tsconfig.json
136136
Info 11 [00:00:34.000] Creating configuration project /user/username/projects/myproject/tsconfig.json
137137
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
138-
CustomRequire:: Resolving myplugin from /a/lib/tsc.js/../../../node_modules
138+
CustomRequire:: Resolving myplugin from /a/pluginprobe1/node_modules
139139
Custom watchFile: /user/username/projects/myproject/tsconfig.json 2000 {"watchFactory":"myplugin"}
140140
Info 13 [00:00:36.000] Config: /user/username/projects/myproject/tsconfig.json : {
141141
"rootNames": [

tests/baselines/reference/tsserver/watchEnvironment/watchFactory-as-configuration-of-host-with-pluginoverride-object.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ Info 9 [00:00:32.000] Search path: /user/username/projects/myproject
138138
Info 10 [00:00:33.000] For info: /user/username/projects/myproject/a.ts :: Config file name: /user/username/projects/myproject/tsconfig.json
139139
Info 11 [00:00:34.000] Creating configuration project /user/username/projects/myproject/tsconfig.json
140140
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
141-
CustomRequire:: Resolving myplugin from /a/lib/tsc.js/../../../node_modules
141+
CustomRequire:: Resolving myplugin from /a/pluginprobe1/node_modules
142142
Custom watchFile: /user/username/projects/myproject/tsconfig.json 2000 {"watchFactory":{"name":"myplugin","myconfig":"somethingelse"}}
143143
Info 13 [00:00:36.000] Config: /user/username/projects/myproject/tsconfig.json : {
144144
"rootNames": [

0 commit comments

Comments
 (0)