Skip to content

Commit 8d3125b

Browse files
authored
Allows plugin to register commands (#44291)
* Pass session into plugin * Use unknown message type * Add missing unknown * use editor services insted of every project * Fix baseline * Add plugin test * Avoid type parameter * Accept baseline
1 parent 0f216f3 commit 8d3125b

File tree

6 files changed

+64
-3
lines changed

6 files changed

+64
-3
lines changed

src/server/editorServices.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,7 @@ namespace ts.server {
411411
/** @deprecated use serverMode instead */
412412
syntaxOnly?: boolean;
413413
serverMode?: LanguageServiceMode;
414+
session: Session<unknown> | undefined;
414415
}
415416

416417
interface OriginalFileInfo { fileName: NormalizedPath; path: Path; }
@@ -795,6 +796,9 @@ namespace ts.server {
795796
/*@internal*/
796797
private packageJsonFilesMap: ESMap<Path, FileWatcher> | undefined;
797798

799+
/*@internal*/
800+
readonly session: Session<unknown> | undefined;
801+
798802

799803
private performanceEventHandler?: PerformanceEventHandler;
800804

@@ -812,6 +816,8 @@ namespace ts.server {
812816
this.pluginProbeLocations = opts.pluginProbeLocations || emptyArray;
813817
this.allowLocalPluginLoads = !!opts.allowLocalPluginLoads;
814818
this.typesMapLocation = (opts.typesMapLocation === undefined) ? combinePaths(getDirectoryPath(this.getExecutingFilePath()), "typesMap.json") : opts.typesMapLocation;
819+
this.session = opts.session;
820+
815821
if (opts.serverMode !== undefined) {
816822
this.serverMode = opts.serverMode;
817823
this.syntaxOnly = this.serverMode === LanguageServiceMode.Syntactic;

src/server/project.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ namespace ts.server {
8484
languageService: LanguageService;
8585
languageServiceHost: LanguageServiceHost;
8686
serverHost: ServerHost;
87+
session?: Session<unknown>;
8788
config: any;
8889
}
8990

@@ -1610,7 +1611,8 @@ namespace ts.server {
16101611
project: this,
16111612
languageService: this.languageService,
16121613
languageServiceHost: this,
1613-
serverHost: this.projectService.host
1614+
serverHost: this.projectService.host,
1615+
session: this.projectService.session
16141616
};
16151617

16161618
const pluginModule = pluginModuleFactory({ typescript: ts });
@@ -2119,7 +2121,7 @@ namespace ts.server {
21192121
/*compileOnSaveEnabled*/ false,
21202122
/*watchOptions*/ undefined,
21212123
cachedDirectoryStructureHost,
2122-
getDirectoryPath(configFileName),
2124+
getDirectoryPath(configFileName)
21232125
);
21242126
}
21252127

src/server/session.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -775,6 +775,7 @@ namespace ts.server {
775775
typesMapLocation: opts.typesMapLocation,
776776
syntaxOnly: opts.syntaxOnly,
777777
serverMode: opts.serverMode,
778+
session: this
778779
};
779780
this.projectService = new ProjectService(settings);
780781
this.projectService.setPerformanceEventHandler(this.performanceEventHandler.bind(this));

src/testRunner/unittests/tsserver/helpers.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,7 @@ namespace ts.projectSystem {
423423
super({
424424
host,
425425
logger,
426+
session: undefined,
426427
cancellationToken,
427428
useSingleInferredProject,
428429
useInferredProjectPerProjectRoot: false,

src/testRunner/unittests/tsserver/plugins.ts

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,31 @@
11
namespace ts.projectSystem {
22
describe("unittests:: tsserver:: plugins loading", () => {
3+
const testProtocolCommand = "testProtocolCommand";
4+
const testProtocolCommandRequest = "testProtocolCommandRequest";
5+
const testProtocolCommandResponse = "testProtocolCommandResponse";
6+
37
function createHostWithPlugin(files: readonly File[]) {
48
const host = createServerHost(files);
59
const pluginsLoaded: string[] = [];
10+
const protocolHandlerRequests: [string, string][] = [];
611
host.require = (_initialPath, moduleName) => {
712
pluginsLoaded.push(moduleName);
813
return {
914
module: () => ({
1015
create(info: server.PluginCreateInfo) {
16+
info.session?.addProtocolHandler(testProtocolCommand, request => {
17+
protocolHandlerRequests.push([request.command, request.arguments]);
18+
return {
19+
response: testProtocolCommandResponse
20+
};
21+
});
1122
return Harness.LanguageService.makeDefaultProxy(info);
1223
}
1324
}),
1425
error: undefined
1526
};
1627
};
17-
return { host, pluginsLoaded };
28+
return { host, pluginsLoaded, protocolHandlerRequests };
1829
}
1930

2031
it("With local plugins", () => {
@@ -51,5 +62,43 @@ namespace ts.projectSystem {
5162
service.openClientFile(aTs.path);
5263
assert.deepEqual(pluginsLoaded, expectedToLoad);
5364
});
65+
66+
it("With session and custom protocol message", () => {
67+
const pluginName = "some-plugin";
68+
const expectedToLoad = [pluginName];
69+
const aTs: File = { path: "/a.ts", content: `class c { prop = "hello"; foo() { return this.prop; } }` };
70+
const tsconfig: File = {
71+
path: "/tsconfig.json",
72+
content: JSON.stringify({
73+
compilerOptions: {
74+
plugins: [
75+
{ name: pluginName }
76+
]
77+
}
78+
})
79+
};
80+
81+
const { host, pluginsLoaded, protocolHandlerRequests } = createHostWithPlugin([aTs, tsconfig, libFile]);
82+
const session = createSession(host);
83+
84+
const service = createProjectService(host, { session });
85+
service.openClientFile(aTs.path);
86+
assert.deepEqual(pluginsLoaded, expectedToLoad);
87+
88+
const resp = session.executeCommandSeq({
89+
command: testProtocolCommand,
90+
arguments: testProtocolCommandRequest
91+
});
92+
93+
assert.strictEqual(protocolHandlerRequests.length, 1);
94+
const [command, args] = protocolHandlerRequests[0];
95+
assert.strictEqual(command, testProtocolCommand);
96+
assert.strictEqual(args, testProtocolCommandRequest);
97+
98+
const expectedResp: server.HandlerResponse = {
99+
response: testProtocolCommandResponse
100+
};
101+
assert.deepEqual(resp, expectedResp);
102+
});
54103
});
55104
}

tests/baselines/reference/api/tsserverlibrary.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9558,6 +9558,7 @@ declare namespace ts.server {
95589558
languageService: LanguageService;
95599559
languageServiceHost: LanguageServiceHost;
95609560
serverHost: ServerHost;
9561+
session?: Session<unknown>;
95619562
config: any;
95629563
}
95639564
interface PluginModule {
@@ -9949,6 +9950,7 @@ declare namespace ts.server {
99499950
/** @deprecated use serverMode instead */
99509951
syntaxOnly?: boolean;
99519952
serverMode?: LanguageServiceMode;
9953+
session: Session<unknown> | undefined;
99529954
}
99539955
export interface WatchOptionsAndErrors {
99549956
watchOptions: WatchOptions;

0 commit comments

Comments
 (0)