11import type { CMKConfig } from '@css-modules-kit/core' ;
22import { createMatchesPattern , createResolver , readConfigFile } from '@css-modules-kit/core' ;
33import { TsConfigFileNotFoundError } from '@css-modules-kit/core' ;
4+ import type { Language } from '@volar/language-core' ;
45import { createLanguageServicePlugin } from '@volar/typescript/lib/quickstart/createLanguageServicePlugin.js' ;
6+ import type ts from 'typescript' ;
57import { createCSSLanguagePlugin } from './language-plugin.js' ;
68import { proxyLanguageService } from './language-service/proxy.js' ;
9+ import { createDocumentLinkHandler } from './protocol-handler/documentLink.js' ;
10+ import { createRenameHandler } from './protocol-handler/rename.js' ;
11+ import { createRenameInfoHandler } from './protocol-handler/renameInfo.js' ;
12+
13+ const projectToLanguage = new WeakMap < ts . server . Project , Language < string > > ( ) ;
714
815const plugin = createLanguageServicePlugin ( ( ts , info ) => {
916 if ( info . project . projectKind !== ts . server . ProjectKind . Configured ) {
@@ -53,6 +60,7 @@ const plugin = createLanguageServicePlugin((ts, info) => {
5360 return {
5461 languagePlugins : [ createCSSLanguagePlugin ( resolver , matchesPattern , config ) ] ,
5562 setup : ( language ) => {
63+ projectToLanguage . set ( info . project , language ) ;
5664 info . languageService = proxyLanguageService (
5765 language ,
5866 info . languageService ,
@@ -61,6 +69,42 @@ const plugin = createLanguageServicePlugin((ts, info) => {
6169 matchesPattern ,
6270 config ,
6371 ) ;
72+ if ( info . session ) {
73+ // Register protocol handlers for "Request Forwarding to tsserver".
74+ // See https://github.com/mizdra/css-modules-kit/pull/207 for more details.
75+
76+ // `info.session.addProtocolHandler` cannot register multiple handlers with the same command name.
77+ // Attempting to do so will result in an error.
78+ //
79+ // By the way, tsserver creates one ConfiguredProject for each tsconfig.json file. Then, tsserver
80+ // initializes each plugin for each ConfiguredProject. This means that if there are multiple
81+ // tsconfig.json files, the handler will be registered multiple times.
82+ //
83+ // Therefore, we will do the following:
84+ // - Implement the handler to handle files from different projects
85+ // - Skip registration if the handler is already registered
86+ try {
87+ info . session . addProtocolHandler ( '_css-modules-kit:rename' , createRenameHandler ( info . project . projectService ) ) ;
88+ info . session . addProtocolHandler (
89+ '_css-modules-kit:renameInfo' ,
90+ createRenameInfoHandler ( info . project . projectService ) ,
91+ ) ;
92+ info . session . addProtocolHandler (
93+ '_css-modules-kit:documentLink' ,
94+ createDocumentLinkHandler ( info . project . projectService , projectToLanguage , resolver ) ,
95+ ) ;
96+ } catch {
97+ info . project . projectService . logger . info (
98+ `[@css-modules-kit/ts-plugin] Skipping protocol handler registration because the handlers are already registered.` ,
99+ ) ;
100+ }
101+ } else {
102+ // When a plugin is used via tsserver from the editor, the session is always available.
103+ // However, when a plugin is used via the TypeScript Compiler API, the session may not be available.
104+ info . project . projectService . logger . info (
105+ '[@css-modules-kit/ts-plugin] info: Skipping protocol handler registration because session is not available.' ,
106+ ) ;
107+ }
64108 } ,
65109 } ;
66110} ) ;
0 commit comments