Skip to content
This repository was archived by the owner on Oct 16, 2020. It is now read-only.

Commit 7e28fa4

Browse files
committed
fix: Add documentation and reorder functions
1 parent ce4fd53 commit 7e28fa4

File tree

1 file changed

+72
-32
lines changed

1 file changed

+72
-32
lines changed

src/project-manager.ts

Lines changed: 72 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,24 @@ import {
2424
export type ConfigType = 'js' | 'ts';
2525

2626
// definitions from from TypeScript server/project.ts
27-
interface Project {
28-
projectService: {
29-
logger: Logger;
30-
};
31-
}
3227

33-
type ServerHost = object;
28+
/**
29+
* A plugin exports an initialization function, injected with
30+
* the current typescript instance
31+
*/
32+
type PluginModuleFactory = (mod: { typescript: typeof ts }) => PluginModule;
33+
34+
/**
35+
* A plugin presents this API when initialized
36+
*/
37+
interface PluginModule {
38+
create(createInfo: PluginCreateInfo): ts.LanguageService;
39+
getExternalFiles?(proj: Project): string[];
40+
}
3441

42+
/**
43+
* All of tsserver's environment exposed to plugins
44+
*/
3545
interface PluginCreateInfo {
3646
project: Project;
3747
languageService: ts.LanguageService;
@@ -40,14 +50,24 @@ interface PluginCreateInfo {
4050
config: any;
4151
}
4252

43-
type RequireResult = { module: {}, error: undefined } | { module: undefined, error: {} };
44-
45-
interface PluginModule {
46-
create(createInfo: PluginCreateInfo): ts.LanguageService;
47-
getExternalFiles?(proj: Project): string[];
53+
/**
54+
* The portion of tsserver's Project API exposed to plugins
55+
*/
56+
interface Project {
57+
projectService: {
58+
logger: Logger;
59+
};
4860
}
4961

50-
type PluginModuleFactory = (mod: { typescript: typeof ts }) => PluginModule;
62+
/**
63+
* The portion of tsserver's ServerHost API exposed to plugins
64+
*/
65+
type ServerHost = object;
66+
67+
/**
68+
* The result of a node require: a module or an error.
69+
*/
70+
type RequireResult = { module: {}, error: undefined } | { module: undefined, error: {} };
5171

5272
/**
5373
* ProjectManager translates VFS files to one or many projects denoted by [tj]config.json.
@@ -906,6 +926,27 @@ export class ProjectConfiguration {
906926
// TODO: support globalPlugins flag if desired
907927
}
908928

929+
/**
930+
* Tries to load and enable a single plugin
931+
* @param pluginConfigEntry
932+
* @param searchPaths
933+
*/
934+
private enablePlugin(pluginConfigEntry: ts.PluginImport, searchPaths: string[]) {
935+
for (const searchPath of searchPaths) {
936+
const resolvedModule = this.resolveModule(pluginConfigEntry.name, searchPath) as PluginModuleFactory;
937+
if (resolvedModule) {
938+
this.enableProxy(resolvedModule, pluginConfigEntry);
939+
return;
940+
}
941+
}
942+
this.logger.info(`Couldn't find ${pluginConfigEntry.name} anywhere in paths: ${searchPaths.join(',')}`);
943+
}
944+
945+
/**
946+
* Load a plugin use a node require
947+
* @param moduleName
948+
* @param initialDir
949+
*/
909950
private resolveModule(moduleName: string, initialDir: string): {} | undefined {
910951
const resolvedPath = path.resolve(initialDir, 'node_modules');
911952
this.logger.info(`Loading ${moduleName} from ${initialDir} (resolved to ${resolvedPath})`);
@@ -917,6 +958,20 @@ export class ProjectConfiguration {
917958
return result.module;
918959
}
919960

961+
/**
962+
* Resolves a loads a plugin function relative to initialDir
963+
* @param initialDir
964+
* @param moduleName
965+
*/
966+
private requirePlugin(initialDir: string, moduleName: string): RequireResult {
967+
const modulePath = this.resolveJavaScriptModule(moduleName, initialDir, this.fs);
968+
try {
969+
return { module: require(modulePath), error: undefined };
970+
} catch (error) {
971+
return { module: undefined, error };
972+
}
973+
}
974+
920975
// TODO: stolen from moduleNameResolver.ts because marked as internal
921976
/**
922977
* Expose resolution logic to allow us to use Node module resolution logic from arbitrary locations.
@@ -934,26 +989,11 @@ export class ProjectConfiguration {
934989
return resolvedModule.resolvedFileName;
935990
}
936991

937-
private requirePlugin(initialDir: string, moduleName: string): RequireResult {
938-
const modulePath = this.resolveJavaScriptModule(moduleName, initialDir, this.fs);
939-
try {
940-
return { module: require(modulePath), error: undefined };
941-
} catch (error) {
942-
return { module: undefined, error };
943-
}
944-
}
945-
946-
private enablePlugin(pluginConfigEntry: ts.PluginImport, searchPaths: string[]) {
947-
for (const searchPath of searchPaths) {
948-
const resolvedModule = this.resolveModule(pluginConfigEntry.name, searchPath) as PluginModuleFactory;
949-
if (resolvedModule) {
950-
this.enableProxy(resolvedModule, pluginConfigEntry);
951-
return;
952-
}
953-
}
954-
this.logger.info(`Couldn't find ${pluginConfigEntry.name} anywhere in paths: ${searchPaths.join(',')}`);
955-
}
956-
992+
/**
993+
* Replaces the LanguageService with an instance wrapped by the plugin
994+
* @param pluginModuleFactory function to create the module
995+
* @param configEntry extra settings from tsconfig to pass to the plugin module
996+
*/
957997
private enableProxy(pluginModuleFactory: PluginModuleFactory, configEntry: ts.PluginImport) {
958998
try {
959999
if (typeof pluginModuleFactory !== 'function') {

0 commit comments

Comments
 (0)