@css-modules-kit/ts-plugin 0.1.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -2
- package/dist/index.js.map +1 -1
- package/dist/language-plugin.d.ts +2 -2
- package/dist/language-plugin.d.ts.map +1 -1
- package/dist/language-plugin.js +3 -2
- package/dist/language-plugin.js.map +1 -1
- package/dist/language-service/feature/code-fix.d.ts +3 -1
- package/dist/language-service/feature/code-fix.d.ts.map +1 -1
- package/dist/language-service/feature/code-fix.js +31 -5
- package/dist/language-service/feature/code-fix.js.map +1 -1
- package/dist/language-service/feature/completion.d.ts +3 -1
- package/dist/language-service/feature/completion.d.ts.map +1 -1
- package/dist/language-service/feature/completion.js +49 -9
- package/dist/language-service/feature/completion.js.map +1 -1
- package/dist/language-service/feature/definition-and-bound-span.d.ts +4 -0
- package/dist/language-service/feature/definition-and-bound-span.d.ts.map +1 -0
- package/dist/language-service/feature/definition-and-bound-span.js +28 -0
- package/dist/language-service/feature/definition-and-bound-span.js.map +1 -0
- package/dist/language-service/proxy.d.ts +2 -1
- package/dist/language-service/proxy.d.ts.map +1 -1
- package/dist/language-service/proxy.js +7 -3
- package/dist/language-service/proxy.js.map +1 -1
- package/dist/util.d.ts +7 -0
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +35 -0
- package/dist/util.js.map +1 -1
- package/package.json +3 -3
- package/src/index.ts +15 -1
- package/src/language-plugin.ts +8 -2
- package/src/language-service/feature/code-fix.ts +40 -4
- package/src/language-service/feature/completion.ts +75 -9
- package/src/language-service/feature/definition-and-bound-span.ts +28 -0
- package/src/language-service/proxy.ts +9 -3
- package/src/util.ts +39 -0
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAOA,QAAA,MAAM,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAOA,QAAA,MAAM,MAAM,iDA0DV,CAAC;AAEH,SAAS,MAAM,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -30,13 +30,25 @@ const plugin = (0, createLanguageServicePlugin_js_1.createLanguageServicePlugin)
|
|
|
30
30
|
return { languagePlugins: [] };
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
|
+
// tsserver should report a “Cannot find module” error for import statements in CSS Modules that
|
|
34
|
+
// do not exist. However, if `dtsOutDir` is included in `rootDirs` and old .d.ts files remain
|
|
35
|
+
// in `dtsOutDir`, the error will not be reported. Therefore, remove `dtsOutDir` from `rootDirs`.
|
|
36
|
+
const getCompilationSettings = info.languageServiceHost.getCompilationSettings.bind(info.languageServiceHost);
|
|
37
|
+
info.languageServiceHost.getCompilationSettings = () => {
|
|
38
|
+
const settings = { ...getCompilationSettings() };
|
|
39
|
+
if (settings.rootDirs) {
|
|
40
|
+
// TODO: If the `dtsOutDir` is not in `rootDirs`, warn the user.
|
|
41
|
+
settings.rootDirs = settings.rootDirs.filter((dir) => dir !== config.dtsOutDir);
|
|
42
|
+
}
|
|
43
|
+
return settings;
|
|
44
|
+
};
|
|
33
45
|
const moduleResolutionCache = info.languageServiceHost.getModuleResolutionCache?.();
|
|
34
46
|
const resolver = (0, core_1.createResolver)(config.compilerOptions, moduleResolutionCache);
|
|
35
47
|
const matchesPattern = (0, core_1.createMatchesPattern)(config);
|
|
36
48
|
return {
|
|
37
|
-
languagePlugins: [(0, language_plugin_js_1.createCSSLanguagePlugin)(resolver, matchesPattern)],
|
|
49
|
+
languagePlugins: [(0, language_plugin_js_1.createCSSLanguagePlugin)(resolver, matchesPattern, config)],
|
|
38
50
|
setup: (language) => {
|
|
39
|
-
info.languageService = (0, proxy_js_1.proxyLanguageService)(language, info.languageService, info.project, resolver, matchesPattern);
|
|
51
|
+
info.languageService = (0, proxy_js_1.proxyLanguageService)(language, info.languageService, info.project, resolver, matchesPattern, config);
|
|
40
52
|
},
|
|
41
53
|
};
|
|
42
54
|
});
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,gDAA6F;AAC7F,gDAAkE;AAClE,oHAA8G;AAC9G,6DAA+D;AAC/D,0DAAmE;AAEnE,MAAM,MAAM,GAAG,IAAA,4DAA2B,EAAC,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE;IACtD,IAAI,IAAI,CAAC,OAAO,CAAC,WAAW,KAAK,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,UAAU,EAAE,CAAC;QAClE,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,8DAA8D,CAAC,CAAC;QACxG,OAAO,EAAE,eAAe,EAAE,EAAE,EAAE,CAAC;IACjC,CAAC;IAED,IAAI,MAAiB,CAAC;IACtB,IAAI,CAAC;QACH,MAAM,GAAG,IAAA,qBAAc,EAAC,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;QACvD,2BAA2B;QAC3B,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,CACrC,4DAA4D,MAAM,CAAC,cAAc,GAAG,CACrF,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,uDAAuD;QACvD,IAAI,KAAK,YAAY,gCAAyB,EAAE,CAAC;YAC/C,OAAO,EAAE,eAAe,EAAE,EAAE,EAAE,CAAC;QACjC,CAAC;aAAM,CAAC;YACN,IAAI,GAAG,GAAG,8DAA8D,CAAC;YACzE,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;gBAC3B,GAAG,IAAI,OAAO,KAAK,CAAC,OAAO,EAAE,CAAC;gBAC9B,GAAG,IAAI,KAAK,KAAK,CAAC,KAAK,EAAE,CAAC;YAC5B,CAAC;YACD,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC7C,OAAO,EAAE,eAAe,EAAE,EAAE,EAAE,CAAC;QACjC,CAAC;IACH,CAAC;IAED,MAAM,qBAAqB,GAAG,IAAI,CAAC,mBAAmB,CAAC,wBAAwB,EAAE,EAAE,CAAC;IACpF,MAAM,QAAQ,GAAG,IAAA,qBAAc,EAAC,MAAM,CAAC,eAAe,EAAE,qBAAqB,CAAC,CAAC;IAC/E,MAAM,cAAc,GAAG,IAAA,2BAAoB,EAAC,MAAM,CAAC,CAAC;IAEpD,OAAO;QACL,eAAe,EAAE,CAAC,IAAA,4CAAuB,EAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,gDAA6F;AAC7F,gDAAkE;AAClE,oHAA8G;AAC9G,6DAA+D;AAC/D,0DAAmE;AAEnE,MAAM,MAAM,GAAG,IAAA,4DAA2B,EAAC,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE;IACtD,IAAI,IAAI,CAAC,OAAO,CAAC,WAAW,KAAK,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,UAAU,EAAE,CAAC;QAClE,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,8DAA8D,CAAC,CAAC;QACxG,OAAO,EAAE,eAAe,EAAE,EAAE,EAAE,CAAC;IACjC,CAAC;IAED,IAAI,MAAiB,CAAC;IACtB,IAAI,CAAC;QACH,MAAM,GAAG,IAAA,qBAAc,EAAC,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;QACvD,2BAA2B;QAC3B,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,CACrC,4DAA4D,MAAM,CAAC,cAAc,GAAG,CACrF,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,uDAAuD;QACvD,IAAI,KAAK,YAAY,gCAAyB,EAAE,CAAC;YAC/C,OAAO,EAAE,eAAe,EAAE,EAAE,EAAE,CAAC;QACjC,CAAC;aAAM,CAAC;YACN,IAAI,GAAG,GAAG,8DAA8D,CAAC;YACzE,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;gBAC3B,GAAG,IAAI,OAAO,KAAK,CAAC,OAAO,EAAE,CAAC;gBAC9B,GAAG,IAAI,KAAK,KAAK,CAAC,KAAK,EAAE,CAAC;YAC5B,CAAC;YACD,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC7C,OAAO,EAAE,eAAe,EAAE,EAAE,EAAE,CAAC;QACjC,CAAC;IACH,CAAC;IAED,gGAAgG;IAChG,6FAA6F;IAC7F,iGAAiG;IACjG,MAAM,sBAAsB,GAAG,IAAI,CAAC,mBAAmB,CAAC,sBAAsB,CAAC,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;IAC9G,IAAI,CAAC,mBAAmB,CAAC,sBAAsB,GAAG,GAAG,EAAE;QACrD,MAAM,QAAQ,GAAG,EAAE,GAAG,sBAAsB,EAAE,EAAE,CAAC;QACjD,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;YACtB,gEAAgE;YAChE,QAAQ,CAAC,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,KAAK,MAAM,CAAC,SAAS,CAAC,CAAC;QAClF,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC,CAAC;IAEF,MAAM,qBAAqB,GAAG,IAAI,CAAC,mBAAmB,CAAC,wBAAwB,EAAE,EAAE,CAAC;IACpF,MAAM,QAAQ,GAAG,IAAA,qBAAc,EAAC,MAAM,CAAC,eAAe,EAAE,qBAAqB,CAAC,CAAC;IAC/E,MAAM,cAAc,GAAG,IAAA,2BAAoB,EAAC,MAAM,CAAC,CAAC;IAEpD,OAAO;QACL,eAAe,EAAE,CAAC,IAAA,4CAAuB,EAAC,QAAQ,EAAE,cAAc,EAAE,MAAM,CAAC,CAAC;QAC5E,KAAK,EAAE,CAAC,QAAQ,EAAE,EAAE;YAClB,IAAI,CAAC,eAAe,GAAG,IAAA,+BAAoB,EACzC,QAAQ,EACR,IAAI,CAAC,eAAe,EACpB,IAAI,CAAC,OAAO,EACZ,QAAQ,EACR,cAAc,EACd,MAAM,CACP,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,iBAAS,MAAM,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CSSModule, DiagnosticWithLocation, MatchesPattern, Resolver } from '@css-modules-kit/core';
|
|
1
|
+
import type { CMKConfig, CSSModule, DiagnosticWithLocation, MatchesPattern, Resolver } from '@css-modules-kit/core';
|
|
2
2
|
import type { LanguagePlugin, SourceScript, VirtualCode } from '@volar/language-core';
|
|
3
3
|
export declare const LANGUAGE_ID = "css";
|
|
4
4
|
export declare const CMK_DATA_KEY: unique symbol;
|
|
@@ -13,7 +13,7 @@ export interface CSSModuleScript extends SourceScript<string> {
|
|
|
13
13
|
root: CSSModuleVirtualCode;
|
|
14
14
|
};
|
|
15
15
|
}
|
|
16
|
-
export declare function createCSSLanguagePlugin(resolver: Resolver, matchesPattern: MatchesPattern): LanguagePlugin<string, VirtualCode>;
|
|
16
|
+
export declare function createCSSLanguagePlugin(resolver: Resolver, matchesPattern: MatchesPattern, config: CMKConfig): LanguagePlugin<string, VirtualCode>;
|
|
17
17
|
export declare function isCSSModuleScript(script: SourceScript<string> | undefined): script is CSSModuleScript;
|
|
18
18
|
export {};
|
|
19
19
|
//# sourceMappingURL=language-plugin.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"language-plugin.d.ts","sourceRoot":"","sources":["../src/language-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,sBAAsB,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"language-plugin.d.ts","sourceRoot":"","sources":["../src/language-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,sBAAsB,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEpH,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAItF,eAAO,MAAM,WAAW,QAAQ,CAAC;AAEjC,eAAO,MAAM,YAAY,eAAiC,CAAC;AAE3D,UAAU,oBAAqB,SAAQ,WAAW;IAChD,CAAC,YAAY,CAAC,EAAE;QACd,SAAS,EAAE,SAAS,CAAC;QACrB,oBAAoB,EAAE,sBAAsB,EAAE,CAAC;KAChD,CAAC;CACH;AAED,MAAM,WAAW,eAAgB,SAAQ,YAAY,CAAC,MAAM,CAAC;IAC3D,SAAS,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,GAAG;QAC7C,IAAI,EAAE,oBAAoB,CAAC;KAC5B,CAAC;CACH;AAED,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,QAAQ,EAClB,cAAc,EAAE,cAAc,EAC9B,MAAM,EAAE,SAAS,GAChB,cAAc,CAAC,MAAM,EAAE,WAAW,CAAC,CAqErC;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,YAAY,CAAC,MAAM,CAAC,GAAG,SAAS,GAAG,MAAM,IAAI,eAAe,CAIrG"}
|
package/dist/language-plugin.js
CHANGED
|
@@ -10,7 +10,7 @@ const core_1 = require("@css-modules-kit/core");
|
|
|
10
10
|
const typescript_1 = __importDefault(require("typescript"));
|
|
11
11
|
exports.LANGUAGE_ID = 'css';
|
|
12
12
|
exports.CMK_DATA_KEY = Symbol('css-modules-kit-data');
|
|
13
|
-
function createCSSLanguagePlugin(resolver, matchesPattern) {
|
|
13
|
+
function createCSSLanguagePlugin(resolver, matchesPattern, config) {
|
|
14
14
|
return {
|
|
15
15
|
getLanguageId(scriptId) {
|
|
16
16
|
if (!scriptId.endsWith('.css'))
|
|
@@ -39,7 +39,8 @@ function createCSSLanguagePlugin(resolver, matchesPattern) {
|
|
|
39
39
|
// So, ts-plugin uses a fault-tolerant Parser to parse CSS.
|
|
40
40
|
safe: true,
|
|
41
41
|
});
|
|
42
|
-
|
|
42
|
+
// eslint-disable-next-line prefer-const
|
|
43
|
+
let { text, mapping, linkedCodeMapping } = (0, core_1.createDts)(cssModule, { resolver, matchesPattern }, { ...config, forTsPlugin: true });
|
|
43
44
|
return {
|
|
44
45
|
id: 'main',
|
|
45
46
|
languageId: exports.LANGUAGE_ID,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"language-plugin.js","sourceRoot":"","sources":["../src/language-plugin.ts"],"names":[],"mappings":";;;;;;AAuBA,
|
|
1
|
+
{"version":3,"file":"language-plugin.js","sourceRoot":"","sources":["../src/language-plugin.ts"],"names":[],"mappings":";;;;;;AAuBA,0DAyEC;AAED,8CAIC;AArGD,gDAAkE;AAGlE,4DAA4B;AAEf,QAAA,WAAW,GAAG,KAAK,CAAC;AAEpB,QAAA,YAAY,GAAG,MAAM,CAAC,sBAAsB,CAAC,CAAC;AAe3D,SAAgB,uBAAuB,CACrC,QAAkB,EAClB,cAA8B,EAC9B,MAAiB;IAEjB,OAAO;QACL,aAAa,CAAC,QAAQ;YACpB,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC;gBAAE,OAAO,SAAS,CAAC;YACjD,OAAO,mBAAW,CAAC;QACrB,CAAC;QACD,iBAAiB,CAAC,QAAQ,EAAE,UAAU,EAAE,QAAQ;YAC9C,IAAI,UAAU,KAAK,mBAAW;gBAAE,OAAO,SAAS,CAAC;YACjD,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC9B,2CAA2C;gBAC3C,qGAAqG;gBACrG,4DAA4D;gBAC5D,OAAO;oBACL,EAAE,EAAE,MAAM;oBACV,UAAU;oBACV,QAAQ;oBACR,QAAQ,EAAE,EAAE;iBACb,CAAC;YACJ,CAAC;YAED,MAAM,MAAM,GAAG,QAAQ,CAAC,SAAS,EAAE,CAAC;YACpC,MAAM,aAAa,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;YAClD,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,GAAG,IAAA,qBAAc,EAAC,aAAa,EAAE;gBAC/D,QAAQ,EAAE,QAAQ;gBAClB,sFAAsF;gBACtF,2DAA2D;gBAC3D,IAAI,EAAE,IAAI;aACX,CAAC,CAAC;YACH,wCAAwC;YACxC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,iBAAiB,EAAE,GAAG,IAAA,gBAAS,EAClD,SAAS,EACT,EAAE,QAAQ,EAAE,cAAc,EAAE,EAC5B,EAAE,GAAG,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,CACjC,CAAC;YACF,OAAO;gBACL,EAAE,EAAE,MAAM;gBACV,UAAU,EAAE,mBAAW;gBACvB,QAAQ,EAAE;oBACR,OAAO,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC;oBAC/C,SAAS,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM;oBAC5B,cAAc,EAAE,GAAG,EAAE,CAAC,SAAS;iBAChC;gBACD,qEAAqE;gBACrE,QAAQ,EAAE,CAAC,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,EAAE,CAAC;gBACtD,uGAAuG;gBACvG,kBAAkB,EAAE,CAAC,EAAE,GAAG,iBAAiB,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;gBAC/D,CAAC,oBAAY,CAAC,EAAE;oBACd,SAAS;oBACT,oBAAoB,EAAE,WAAW;iBAClC;aACF,CAAC;QACJ,CAAC;QACD,UAAU,EAAE;YACV,mBAAmB,EAAE;gBACnB;oBACE,SAAS,EAAE,KAAK;oBAChB,cAAc,EAAE,IAAI;oBACpB,UAAU,EAAE,oBAAE,CAAC,UAAU,CAAC,EAAE;iBAC7B;aACF;YACD,gBAAgB,CAAC,IAAI;gBACnB,OAAO;oBACL,IAAI,EAAE,IAAI;oBACV,SAAS,EAAE,oBAAE,CAAC,SAAS,CAAC,EAAE;oBAC1B,UAAU,EAAE,oBAAE,CAAC,UAAU,CAAC,EAAE;iBAC7B,CAAC;YACJ,CAAC;SACF;KACF,CAAC;AACJ,CAAC;AAED,SAAgB,iBAAiB,CAAC,MAAwC;IACxE,OAAO,CACL,CAAC,CAAC,MAAM,IAAI,MAAM,CAAC,UAAU,KAAK,mBAAW,IAAI,CAAC,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,IAAI,oBAAY,IAAI,MAAM,CAAC,SAAS,CAAC,IAAI,CACnH,CAAC;AACJ,CAAC"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import type { CMKConfig, Resolver } from '@css-modules-kit/core';
|
|
1
2
|
import type { Language } from '@volar/language-core';
|
|
2
3
|
import ts from 'typescript';
|
|
4
|
+
export declare const CANNOT_FIND_NAME_ERROR_CODE = 2304;
|
|
3
5
|
export declare const PROPERTY_DOES_NOT_EXIST_ERROR_CODE = 2339;
|
|
4
|
-
export declare function getCodeFixesAtPosition(language: Language<string>, languageService: ts.LanguageService, project: ts.server.Project): ts.LanguageService['getCodeFixesAtPosition'];
|
|
6
|
+
export declare function getCodeFixesAtPosition(language: Language<string>, languageService: ts.LanguageService, project: ts.server.Project, resolver: Resolver, config: CMKConfig): ts.LanguageService['getCodeFixesAtPosition'];
|
|
5
7
|
//# sourceMappingURL=code-fix.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"code-fix.d.ts","sourceRoot":"","sources":["../../../src/language-service/feature/code-fix.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"code-fix.d.ts","sourceRoot":"","sources":["../../../src/language-service/feature/code-fix.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,MAAM,YAAY,CAAC;AAK5B,eAAO,MAAM,2BAA2B,OAAO,CAAC;AAChD,eAAO,MAAM,kCAAkC,OAAO,CAAC;AAEvD,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,EAC1B,eAAe,EAAE,EAAE,CAAC,eAAe,EACnC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,EAC1B,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,SAAS,GAChB,EAAE,CAAC,eAAe,CAAC,wBAAwB,CAAC,CAmC9C"}
|
|
@@ -3,17 +3,23 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.PROPERTY_DOES_NOT_EXIST_ERROR_CODE = void 0;
|
|
6
|
+
exports.PROPERTY_DOES_NOT_EXIST_ERROR_CODE = exports.CANNOT_FIND_NAME_ERROR_CODE = void 0;
|
|
7
7
|
exports.getCodeFixesAtPosition = getCodeFixesAtPosition;
|
|
8
8
|
const core_1 = require("@css-modules-kit/core");
|
|
9
9
|
const typescript_1 = __importDefault(require("typescript"));
|
|
10
10
|
const language_plugin_js_1 = require("../../language-plugin.js");
|
|
11
|
-
|
|
11
|
+
const util_js_1 = require("../../util.js");
|
|
12
|
+
// ref: https://github.com/microsoft/TypeScript/blob/220706eb0320ff46fad8bf80a5e99db624ee7dfb/src/compiler/diagnosticMessages.json
|
|
13
|
+
exports.CANNOT_FIND_NAME_ERROR_CODE = 2304;
|
|
12
14
|
exports.PROPERTY_DOES_NOT_EXIST_ERROR_CODE = 2339;
|
|
13
|
-
function getCodeFixesAtPosition(language, languageService, project) {
|
|
15
|
+
function getCodeFixesAtPosition(language, languageService, project, resolver, config) {
|
|
14
16
|
// eslint-disable-next-line max-params
|
|
15
17
|
return (fileName, start, end, errorCodes, formatOptions, preferences) => {
|
|
16
|
-
const prior = Array.from(languageService.getCodeFixesAtPosition(fileName, start, end, errorCodes, formatOptions, preferences
|
|
18
|
+
const prior = Array.from(languageService.getCodeFixesAtPosition(fileName, start, end, errorCodes, formatOptions, (0, util_js_1.createPreferencesForCompletion)(preferences, config)));
|
|
19
|
+
if (config.namedExports && !config.prioritizeNamedImports) {
|
|
20
|
+
(0, util_js_1.convertDefaultImportsToNamespaceImports)(prior, fileName, resolver);
|
|
21
|
+
excludeNamedImports(prior, fileName, resolver);
|
|
22
|
+
}
|
|
17
23
|
if ((0, core_1.isComponentFileName)(fileName)) {
|
|
18
24
|
// If a user is trying to use a non-existent token (e.g. `styles.nonExistToken`), provide a code fix to add the token.
|
|
19
25
|
if (errorCodes.includes(exports.PROPERTY_DOES_NOT_EXIST_ERROR_CODE)) {
|
|
@@ -27,9 +33,29 @@ function getCodeFixesAtPosition(language, languageService, project) {
|
|
|
27
33
|
}
|
|
28
34
|
}
|
|
29
35
|
}
|
|
30
|
-
return prior;
|
|
36
|
+
return prior.filter((codeFix) => codeFix.changes.length > 0);
|
|
31
37
|
};
|
|
32
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
* Exclude code fixes that add named imports (e.g. `import { foo } from './a.module.css'`)
|
|
41
|
+
*/
|
|
42
|
+
function excludeNamedImports(codeFixes, fileName, resolver) {
|
|
43
|
+
for (const codeFix of codeFixes) {
|
|
44
|
+
if (codeFix.fixName !== 'import')
|
|
45
|
+
continue;
|
|
46
|
+
const match = codeFix.description.match(/^Add import from "(.*)"$/u);
|
|
47
|
+
if (!match)
|
|
48
|
+
continue;
|
|
49
|
+
const specifier = match[1];
|
|
50
|
+
const resolved = resolver(specifier, { request: fileName });
|
|
51
|
+
if (!resolved || !(0, core_1.isCSSModuleFile)(resolved))
|
|
52
|
+
continue;
|
|
53
|
+
for (const change of codeFix.changes) {
|
|
54
|
+
change.textChanges = change.textChanges.filter((textChange) => !textChange.newText.startsWith(`import {`));
|
|
55
|
+
}
|
|
56
|
+
codeFix.changes = codeFix.changes.filter((change) => change.textChanges.length > 0);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
33
59
|
/**
|
|
34
60
|
* Get the token consumer at the specified position.
|
|
35
61
|
* If the position is at `styles.foo`, it returns `{ tokenName: 'foo', from: '/path/to/a.module.css' }`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"code-fix.js","sourceRoot":"","sources":["../../../src/language-service/feature/code-fix.ts"],"names":[],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"code-fix.js","sourceRoot":"","sources":["../../../src/language-service/feature/code-fix.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { CMKConfig, Resolver } from '@css-modules-kit/core';
|
|
1
2
|
import ts from 'typescript';
|
|
2
|
-
export declare function getCompletionsAtPosition(languageService: ts.LanguageService): ts.LanguageService['getCompletionsAtPosition'];
|
|
3
|
+
export declare function getCompletionsAtPosition(languageService: ts.LanguageService, config: CMKConfig): ts.LanguageService['getCompletionsAtPosition'];
|
|
4
|
+
export declare function getCompletionEntryDetails(languageService: ts.LanguageService, resolver: Resolver, config: CMKConfig): ts.LanguageService['getCompletionEntryDetails'];
|
|
3
5
|
//# sourceMappingURL=completion.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"completion.d.ts","sourceRoot":"","sources":["../../../src/language-service/feature/completion.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"completion.d.ts","sourceRoot":"","sources":["../../../src/language-service/feature/completion.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjE,OAAO,EAAE,MAAM,YAAY,CAAC;AAG5B,wBAAgB,wBAAwB,CACtC,eAAe,EAAE,EAAE,CAAC,eAAe,EACnC,MAAM,EAAE,SAAS,GAChB,EAAE,CAAC,eAAe,CAAC,0BAA0B,CAAC,CAwChD;AA0CD,wBAAgB,yBAAyB,CACvC,eAAe,EAAE,EAAE,CAAC,eAAe,EACnC,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,SAAS,GAChB,EAAE,CAAC,eAAe,CAAC,2BAA2B,CAAC,CAmBjD"}
|
|
@@ -4,15 +4,19 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.getCompletionsAtPosition = getCompletionsAtPosition;
|
|
7
|
+
exports.getCompletionEntryDetails = getCompletionEntryDetails;
|
|
7
8
|
const core_1 = require("@css-modules-kit/core");
|
|
8
9
|
const typescript_1 = __importDefault(require("typescript"));
|
|
9
|
-
|
|
10
|
+
const util_js_1 = require("../../util.js");
|
|
11
|
+
function getCompletionsAtPosition(languageService, config) {
|
|
10
12
|
return (fileName, position, options, formattingSettings) => {
|
|
11
|
-
const prior = languageService.getCompletionsAtPosition(fileName, position, options, formattingSettings);
|
|
12
|
-
if (
|
|
13
|
+
const prior = languageService.getCompletionsAtPosition(fileName, position, (0, util_js_1.createPreferencesForCompletion)(options ?? {}, config), formattingSettings);
|
|
14
|
+
if (!prior)
|
|
15
|
+
return;
|
|
16
|
+
if ((0, core_1.isComponentFileName)(fileName)) {
|
|
13
17
|
const cssModuleFileName = (0, core_1.getCssModuleFileName)(fileName);
|
|
14
18
|
for (const entry of prior.entries) {
|
|
15
|
-
if (
|
|
19
|
+
if (isDefaultExportedStylesEntry(entry) && entry.data.fileName === cssModuleFileName) {
|
|
16
20
|
// Prioritize the completion of the `styles' import for the current .ts file for usability.
|
|
17
21
|
// NOTE: This is a hack to make the completion item appear at the top
|
|
18
22
|
entry.sortText = '0';
|
|
@@ -23,19 +27,43 @@ function getCompletionsAtPosition(languageService) {
|
|
|
23
27
|
}
|
|
24
28
|
}
|
|
25
29
|
}
|
|
30
|
+
if (config.namedExports && !config.prioritizeNamedImports) {
|
|
31
|
+
// When `namedExports` is enabled, you can write code as follows:
|
|
32
|
+
// ```tsx
|
|
33
|
+
// import { button } from './a.module.css';
|
|
34
|
+
// const Button = () => <button className={button}>Click me!</button>;
|
|
35
|
+
// ```
|
|
36
|
+
// However, it is more common to use namespace imports for styles.
|
|
37
|
+
// ```tsx
|
|
38
|
+
// import * as styles from './a.module.css';
|
|
39
|
+
// const Button = () => <button className={styles.button}>Click me!</button>;
|
|
40
|
+
// ```
|
|
41
|
+
// Therefore, completion for tokens like `button` is disabled.
|
|
42
|
+
prior.entries = prior.entries.filter((entry) => !isNamedExportedTokenEntry(entry));
|
|
43
|
+
}
|
|
26
44
|
return prior;
|
|
27
45
|
};
|
|
28
46
|
}
|
|
29
47
|
/**
|
|
30
|
-
* Check if the completion entry is the `styles` entry
|
|
48
|
+
* Check if the completion entry is the default exported `styles` entry.
|
|
31
49
|
*/
|
|
32
|
-
function
|
|
50
|
+
function isDefaultExportedStylesEntry(entry) {
|
|
33
51
|
return (entry.name === core_1.STYLES_EXPORT_NAME &&
|
|
34
|
-
entry.data &&
|
|
52
|
+
entry.data !== undefined &&
|
|
35
53
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison
|
|
36
54
|
entry.data.exportName === typescript_1.default.InternalSymbolName.Default &&
|
|
37
|
-
entry.data.fileName &&
|
|
38
|
-
entry.data.fileName
|
|
55
|
+
entry.data.fileName !== undefined &&
|
|
56
|
+
(0, core_1.isCSSModuleFile)(entry.data.fileName));
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Check if the completion entry is a named exported token entry.
|
|
60
|
+
*/
|
|
61
|
+
function isNamedExportedTokenEntry(entry) {
|
|
62
|
+
return (entry.data !== undefined &&
|
|
63
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison
|
|
64
|
+
entry.data.exportName !== typescript_1.default.InternalSymbolName.Default &&
|
|
65
|
+
entry.data.fileName !== undefined &&
|
|
66
|
+
(0, core_1.isCSSModuleFile)(entry.data.fileName));
|
|
39
67
|
}
|
|
40
68
|
function isClassNamePropEntry(entry) {
|
|
41
69
|
return (entry.name === 'className' &&
|
|
@@ -43,4 +71,16 @@ function isClassNamePropEntry(entry) {
|
|
|
43
71
|
(entry.insertText === 'className="$1"' || entry.insertText === "className='$1'") &&
|
|
44
72
|
entry.isSnippet);
|
|
45
73
|
}
|
|
74
|
+
function getCompletionEntryDetails(languageService, resolver, config) {
|
|
75
|
+
// eslint-disable-next-line max-params
|
|
76
|
+
return (fileName, position, entryName, formatOptions, source, preferences, data) => {
|
|
77
|
+
const details = languageService.getCompletionEntryDetails(fileName, position, entryName, formatOptions, source, preferences, data);
|
|
78
|
+
if (!details)
|
|
79
|
+
return undefined;
|
|
80
|
+
if (config.namedExports && !config.prioritizeNamedImports && details.codeActions) {
|
|
81
|
+
(0, util_js_1.convertDefaultImportsToNamespaceImports)(details.codeActions, fileName, resolver);
|
|
82
|
+
}
|
|
83
|
+
return details;
|
|
84
|
+
};
|
|
85
|
+
}
|
|
46
86
|
//# sourceMappingURL=completion.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"completion.js","sourceRoot":"","sources":["../../../src/language-service/feature/completion.ts"],"names":[],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"completion.js","sourceRoot":"","sources":["../../../src/language-service/feature/completion.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Language } from '@volar/language-core';
|
|
2
|
+
import type ts from 'typescript';
|
|
3
|
+
export declare function getDefinitionAndBoundSpan(language: Language<string>, languageService: ts.LanguageService): ts.LanguageService['getDefinitionAndBoundSpan'];
|
|
4
|
+
//# sourceMappingURL=definition-and-bound-span.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"definition-and-bound-span.d.ts","sourceRoot":"","sources":["../../../src/language-service/feature/definition-and-bound-span.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAGjC,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,EAC1B,eAAe,EAAE,EAAE,CAAC,eAAe,GAClC,EAAE,CAAC,eAAe,CAAC,2BAA2B,CAAC,CAoBjD"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getDefinitionAndBoundSpan = getDefinitionAndBoundSpan;
|
|
4
|
+
const language_plugin_js_1 = require("../../language-plugin.js");
|
|
5
|
+
function getDefinitionAndBoundSpan(language, languageService) {
|
|
6
|
+
return (...args) => {
|
|
7
|
+
const result = languageService.getDefinitionAndBoundSpan(...args);
|
|
8
|
+
if (!result)
|
|
9
|
+
return;
|
|
10
|
+
if (!result.definitions)
|
|
11
|
+
return result;
|
|
12
|
+
for (const def of result.definitions) {
|
|
13
|
+
const script = language.scripts.get(def.fileName);
|
|
14
|
+
if ((0, language_plugin_js_1.isCSSModuleScript)(script)) {
|
|
15
|
+
const cssModule = script.generated.root[language_plugin_js_1.CMK_DATA_KEY].cssModule;
|
|
16
|
+
const token = cssModule.localTokens.find((t) => t.name === def.name);
|
|
17
|
+
if (token?.declarationLoc) {
|
|
18
|
+
def.contextSpan = {
|
|
19
|
+
start: token.declarationLoc.start.offset,
|
|
20
|
+
length: token.declarationLoc.end.offset - token.declarationLoc.start.offset,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return result;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=definition-and-bound-span.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"definition-and-bound-span.js","sourceRoot":"","sources":["../../../src/language-service/feature/definition-and-bound-span.ts"],"names":[],"mappings":";;AAIA,8DAuBC;AAzBD,iEAA2E;AAE3E,SAAgB,yBAAyB,CACvC,QAA0B,EAC1B,eAAmC;IAEnC,OAAO,CAAC,GAAG,IAAI,EAAE,EAAE;QACjB,MAAM,MAAM,GAAG,eAAe,CAAC,yBAAyB,CAAC,GAAG,IAAI,CAAC,CAAC;QAClE,IAAI,CAAC,MAAM;YAAE,OAAO;QACpB,IAAI,CAAC,MAAM,CAAC,WAAW;YAAE,OAAO,MAAM,CAAC;QACvC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;YACrC,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAClD,IAAI,IAAA,sCAAiB,EAAC,MAAM,CAAC,EAAE,CAAC;gBAC9B,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,iCAAY,CAAC,CAAC,SAAS,CAAC;gBAChE,MAAM,KAAK,GAAG,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,CAAC,CAAC;gBACrE,IAAI,KAAK,EAAE,cAAc,EAAE,CAAC;oBAC1B,GAAG,CAAC,WAAW,GAAG;wBAChB,KAAK,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,MAAM;wBACxC,MAAM,EAAE,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,MAAM,GAAG,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,MAAM;qBAC5E,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import type { CMKConfig } from '@css-modules-kit/core';
|
|
1
2
|
import { type MatchesPattern, type Resolver } from '@css-modules-kit/core';
|
|
2
3
|
import type { Language } from '@volar/language-core';
|
|
3
4
|
import type ts from 'typescript';
|
|
4
|
-
export declare function proxyLanguageService(language: Language<string>, languageService: ts.LanguageService, project: ts.server.Project, resolver: Resolver, matchesPattern: MatchesPattern): ts.LanguageService;
|
|
5
|
+
export declare function proxyLanguageService(language: Language<string>, languageService: ts.LanguageService, project: ts.server.Project, resolver: Resolver, matchesPattern: MatchesPattern, config: CMKConfig): ts.LanguageService;
|
|
5
6
|
//# sourceMappingURL=proxy.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../../src/language-service/proxy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,cAAc,EAAE,KAAK,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAChG,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../../src/language-service/proxy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAuB,KAAK,cAAc,EAAE,KAAK,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAChG,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAUjC,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,EAC1B,eAAe,EAAE,EAAE,CAAC,eAAe,EACnC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,EAC1B,QAAQ,EAAE,QAAQ,EAClB,cAAc,EAAE,cAAc,EAC9B,MAAM,EAAE,SAAS,GAChB,EAAE,CAAC,eAAe,CAoCpB"}
|
|
@@ -5,10 +5,12 @@ const core_1 = require("@css-modules-kit/core");
|
|
|
5
5
|
const language_plugin_js_1 = require("../language-plugin.js");
|
|
6
6
|
const code_fix_js_1 = require("./feature/code-fix.js");
|
|
7
7
|
const completion_js_1 = require("./feature/completion.js");
|
|
8
|
+
const definition_and_bound_span_js_1 = require("./feature/definition-and-bound-span.js");
|
|
8
9
|
const refactor_js_1 = require("./feature/refactor.js");
|
|
9
10
|
const semantic_diagnostic_js_1 = require("./feature/semantic-diagnostic.js");
|
|
10
11
|
const syntactic_diagnostic_js_1 = require("./feature/syntactic-diagnostic.js");
|
|
11
|
-
|
|
12
|
+
// eslint-disable-next-line max-params
|
|
13
|
+
function proxyLanguageService(language, languageService, project, resolver, matchesPattern, config) {
|
|
12
14
|
const proxy = Object.create(null);
|
|
13
15
|
for (const k of Object.keys(languageService)) {
|
|
14
16
|
const x = languageService[k];
|
|
@@ -28,8 +30,10 @@ function proxyLanguageService(language, languageService, project, resolver, matc
|
|
|
28
30
|
proxy.getSemanticDiagnostics = (0, semantic_diagnostic_js_1.getSemanticDiagnostics)(language, languageService, exportBuilder, resolver, matchesPattern, getCSSModule);
|
|
29
31
|
proxy.getApplicableRefactors = (0, refactor_js_1.getApplicableRefactors)(languageService, project);
|
|
30
32
|
proxy.getEditsForRefactor = (0, refactor_js_1.getEditsForRefactor)(languageService);
|
|
31
|
-
proxy.getCompletionsAtPosition = (0, completion_js_1.getCompletionsAtPosition)(languageService);
|
|
32
|
-
proxy.
|
|
33
|
+
proxy.getCompletionsAtPosition = (0, completion_js_1.getCompletionsAtPosition)(languageService, config);
|
|
34
|
+
proxy.getCompletionEntryDetails = (0, completion_js_1.getCompletionEntryDetails)(languageService, resolver, config);
|
|
35
|
+
proxy.getCodeFixesAtPosition = (0, code_fix_js_1.getCodeFixesAtPosition)(language, languageService, project, resolver, config);
|
|
36
|
+
proxy.getDefinitionAndBoundSpan = (0, definition_and_bound_span_js_1.getDefinitionAndBoundSpan)(language, languageService);
|
|
33
37
|
return proxy;
|
|
34
38
|
}
|
|
35
39
|
//# sourceMappingURL=proxy.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proxy.js","sourceRoot":"","sources":["../../src/language-service/proxy.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"proxy.js","sourceRoot":"","sources":["../../src/language-service/proxy.ts"],"names":[],"mappings":";;AAaA,oDA2CC;AAvDD,gDAAgG;AAGhG,8DAAwE;AACxE,uDAA+D;AAC/D,2DAA8F;AAC9F,yFAAmF;AACnF,uDAAoF;AACpF,6EAA0E;AAC1E,+EAA4E;AAE5E,sCAAsC;AACtC,SAAgB,oBAAoB,CAClC,QAA0B,EAC1B,eAAmC,EACnC,OAA0B,EAC1B,QAAkB,EAClB,cAA8B,EAC9B,MAAiB;IAEjB,MAAM,KAAK,GAAuB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAEtD,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,eAAe,CAAiC,EAAE,CAAC;QAC7E,MAAM,CAAC,GAAG,eAAe,CAAC,CAAC,CAAE,CAAC;QAC9B,yEAAyE;QACzE,mEAAmE;QACnE,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,IAAU,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,eAAe,EAAE,IAAI,CAAC,CAAC;IAC/D,CAAC;IAED,MAAM,YAAY,GAAG,CAAC,IAAY,EAAE,EAAE;QACpC,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC1C,IAAI,IAAA,sCAAiB,EAAC,MAAM,CAAC,EAAE,CAAC;YAC9B,OAAO,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,iCAAY,CAAC,CAAC,SAAS,CAAC;QACvD,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC,CAAC;IACF,MAAM,aAAa,GAAG,IAAA,0BAAmB,EAAC,EAAE,YAAY,EAAE,QAAQ,EAAE,cAAc,EAAE,CAAC,CAAC;IAEtF,KAAK,CAAC,uBAAuB,GAAG,IAAA,iDAAuB,EAAC,QAAQ,EAAE,eAAe,CAAC,CAAC;IACnF,KAAK,CAAC,sBAAsB,GAAG,IAAA,+CAAsB,EACnD,QAAQ,EACR,eAAe,EACf,aAAa,EACb,QAAQ,EACR,cAAc,EACd,YAAY,CACb,CAAC;IACF,KAAK,CAAC,sBAAsB,GAAG,IAAA,oCAAsB,EAAC,eAAe,EAAE,OAAO,CAAC,CAAC;IAChF,KAAK,CAAC,mBAAmB,GAAG,IAAA,iCAAmB,EAAC,eAAe,CAAC,CAAC;IACjE,KAAK,CAAC,wBAAwB,GAAG,IAAA,wCAAwB,EAAC,eAAe,EAAE,MAAM,CAAC,CAAC;IACnF,KAAK,CAAC,yBAAyB,GAAG,IAAA,yCAAyB,EAAC,eAAe,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC/F,KAAK,CAAC,sBAAsB,GAAG,IAAA,oCAAsB,EAAC,QAAQ,EAAE,eAAe,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC5G,KAAK,CAAC,yBAAyB,GAAG,IAAA,wDAAyB,EAAC,QAAQ,EAAE,eAAe,CAAC,CAAC;IAEvF,OAAO,KAAK,CAAC;AACf,CAAC"}
|
package/dist/util.d.ts
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
|
+
import { type CMKConfig, type Resolver } from '@css-modules-kit/core';
|
|
1
2
|
import ts from 'typescript';
|
|
2
3
|
/** The error code used by tsserver to display the css-modules-kit error in the editor. */
|
|
3
4
|
export declare const TS_ERROR_CODE_FOR_CMK_ERROR = 0;
|
|
4
5
|
export declare function convertErrorCategory(category: 'error' | 'warning' | 'suggestion'): ts.DiagnosticCategory;
|
|
6
|
+
export declare function createPreferencesForCompletion<T extends ts.UserPreferences>(preferences: T, config: CMKConfig): T;
|
|
7
|
+
/**
|
|
8
|
+
* Convert default imports to namespace imports for CSS modules.
|
|
9
|
+
* For example, convert `import styles from './styles.module.css'` to `import * as styles from './styles.module.css'`.
|
|
10
|
+
*/
|
|
11
|
+
export declare function convertDefaultImportsToNamespaceImports(codeFixes: ts.CodeFixAction[] | ts.CodeAction[], fileName: string, resolver: Resolver): void;
|
|
5
12
|
//# sourceMappingURL=util.d.ts.map
|
package/dist/util.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B,0FAA0F;AAG1F,eAAO,MAAM,2BAA2B,IAAI,CAAC;AAE7C,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,OAAO,GAAG,SAAS,GAAG,YAAY,GAAG,EAAE,CAAC,kBAAkB,CAWxG"}
|
|
1
|
+
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAmB,KAAK,QAAQ,EAAsB,MAAM,uBAAuB,CAAC;AAC3G,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B,0FAA0F;AAG1F,eAAO,MAAM,2BAA2B,IAAI,CAAC;AAE7C,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,OAAO,GAAG,SAAS,GAAG,YAAY,GAAG,EAAE,CAAC,kBAAkB,CAWxG;AAED,wBAAgB,8BAA8B,CAAC,CAAC,SAAS,EAAE,CAAC,eAAe,EAAE,WAAW,EAAE,CAAC,EAAE,MAAM,EAAE,SAAS,GAAG,CAAC,CAOjH;AACD;;;GAGG;AACH,wBAAgB,uCAAuC,CACrD,SAAS,EAAE,EAAE,CAAC,aAAa,EAAE,GAAG,EAAE,CAAC,UAAU,EAAE,EAC/C,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,QAAQ,GACjB,IAAI,CAoBN"}
|
package/dist/util.js
CHANGED
|
@@ -5,6 +5,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.TS_ERROR_CODE_FOR_CMK_ERROR = void 0;
|
|
7
7
|
exports.convertErrorCategory = convertErrorCategory;
|
|
8
|
+
exports.createPreferencesForCompletion = createPreferencesForCompletion;
|
|
9
|
+
exports.convertDefaultImportsToNamespaceImports = convertDefaultImportsToNamespaceImports;
|
|
10
|
+
const core_1 = require("@css-modules-kit/core");
|
|
8
11
|
const typescript_1 = __importDefault(require("typescript"));
|
|
9
12
|
/** The error code used by tsserver to display the css-modules-kit error in the editor. */
|
|
10
13
|
// NOTE: Use any other number than 1002 or later, as they are reserved by TypeScript's built-in errors.
|
|
@@ -22,4 +25,36 @@ function convertErrorCategory(category) {
|
|
|
22
25
|
throw new Error(`Unknown category: ${String(category)}`);
|
|
23
26
|
}
|
|
24
27
|
}
|
|
28
|
+
function createPreferencesForCompletion(preferences, config) {
|
|
29
|
+
// By default, files in `generated/` are included in the completion candidates.
|
|
30
|
+
// To exclude them, we add the `dtsOutDir` to the `autoImportFileExcludePatterns`.
|
|
31
|
+
return {
|
|
32
|
+
...preferences,
|
|
33
|
+
autoImportFileExcludePatterns: [...(preferences.autoImportFileExcludePatterns ?? []), config.dtsOutDir],
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Convert default imports to namespace imports for CSS modules.
|
|
38
|
+
* For example, convert `import styles from './styles.module.css'` to `import * as styles from './styles.module.css'`.
|
|
39
|
+
*/
|
|
40
|
+
function convertDefaultImportsToNamespaceImports(codeFixes, fileName, resolver) {
|
|
41
|
+
for (const codeFix of codeFixes) {
|
|
42
|
+
if ('fixName' in codeFix && codeFix.fixName !== 'import')
|
|
43
|
+
continue;
|
|
44
|
+
// Check if the code fix is to add an import for a CSS module.
|
|
45
|
+
const match = codeFix.description.match(/^Add import from "(.*)"$/u);
|
|
46
|
+
if (!match)
|
|
47
|
+
continue;
|
|
48
|
+
const specifier = match[1];
|
|
49
|
+
const resolved = resolver(specifier, { request: fileName });
|
|
50
|
+
if (!resolved || !(0, core_1.isCSSModuleFile)(resolved))
|
|
51
|
+
continue;
|
|
52
|
+
// If the specifier is a CSS module, convert the import to a namespace import.
|
|
53
|
+
for (const change of codeFix.changes) {
|
|
54
|
+
for (const textChange of change.textChanges) {
|
|
55
|
+
textChange.newText = textChange.newText.replace(`import ${core_1.STYLES_EXPORT_NAME} from`, `import * as ${core_1.STYLES_EXPORT_NAME} from`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
25
60
|
//# sourceMappingURL=util.js.map
|
package/dist/util.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":";;;;;;AAQA,oDAWC;AAED,wEAOC;AAKD,0FAwBC;AAzDD,gDAA2G;AAC3G,4DAA4B;AAE5B,0FAA0F;AAC1F,uGAAuG;AACvG,kIAAkI;AACrH,QAAA,2BAA2B,GAAG,CAAC,CAAC;AAE7C,SAAgB,oBAAoB,CAAC,QAA4C;IAC/E,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,OAAO;YACV,OAAO,oBAAE,CAAC,kBAAkB,CAAC,KAAK,CAAC;QACrC,KAAK,SAAS;YACZ,OAAO,oBAAE,CAAC,kBAAkB,CAAC,OAAO,CAAC;QACvC,KAAK,YAAY;YACf,OAAO,oBAAE,CAAC,kBAAkB,CAAC,UAAU,CAAC;QAC1C;YACE,MAAM,IAAI,KAAK,CAAC,qBAAqB,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IAC7D,CAAC;AACH,CAAC;AAED,SAAgB,8BAA8B,CAA+B,WAAc,EAAE,MAAiB;IAC5G,+EAA+E;IAC/E,kFAAkF;IAClF,OAAO;QACL,GAAG,WAAW;QACd,6BAA6B,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,6BAA6B,IAAI,EAAE,CAAC,EAAE,MAAM,CAAC,SAAS,CAAC;KACxG,CAAC;AACJ,CAAC;AACD;;;GAGG;AACH,SAAgB,uCAAuC,CACrD,SAA+C,EAC/C,QAAgB,EAChB,QAAkB;IAElB,KAAK,MAAM,OAAO,IAAI,SAAS,EAAE,CAAC;QAChC,IAAI,SAAS,IAAI,OAAO,IAAI,OAAO,CAAC,OAAO,KAAK,QAAQ;YAAE,SAAS;QACnE,8DAA8D;QAC9D,MAAM,KAAK,GAAG,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;QACrE,IAAI,CAAC,KAAK;YAAE,SAAS;QACrB,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC;QAC5B,MAAM,QAAQ,GAAG,QAAQ,CAAC,SAAS,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC5D,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAA,sBAAe,EAAC,QAAQ,CAAC;YAAE,SAAS;QAEtD,8EAA8E;QAC9E,KAAK,MAAM,MAAM,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YACrC,KAAK,MAAM,UAAU,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;gBAC5C,UAAU,CAAC,OAAO,GAAG,UAAU,CAAC,OAAO,CAAC,OAAO,CAC7C,UAAU,yBAAkB,OAAO,EACnC,eAAe,yBAAkB,OAAO,CACzC,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@css-modules-kit/ts-plugin",
|
|
3
3
|
"description": "A TypeScript Language Service Plugin for CSS Modules",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.3.0",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"repository": {
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"build": "tsc -b tsconfig.build.json"
|
|
18
18
|
},
|
|
19
19
|
"engines": {
|
|
20
|
-
"node": ">=
|
|
20
|
+
"node": ">=20.19.0"
|
|
21
21
|
},
|
|
22
22
|
"publishConfig": {
|
|
23
23
|
"access": "public",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@volar/language-core": "^2.4.11",
|
|
41
41
|
"@volar/typescript": "^2.4.11",
|
|
42
|
-
"@css-modules-kit/core": "^0.
|
|
42
|
+
"@css-modules-kit/core": "^0.4.0"
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|
|
45
45
|
"typescript": ">=5.6.3"
|
package/src/index.ts
CHANGED
|
@@ -33,12 +33,25 @@ const plugin = createLanguageServicePlugin((ts, info) => {
|
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
// tsserver should report a “Cannot find module” error for import statements in CSS Modules that
|
|
37
|
+
// do not exist. However, if `dtsOutDir` is included in `rootDirs` and old .d.ts files remain
|
|
38
|
+
// in `dtsOutDir`, the error will not be reported. Therefore, remove `dtsOutDir` from `rootDirs`.
|
|
39
|
+
const getCompilationSettings = info.languageServiceHost.getCompilationSettings.bind(info.languageServiceHost);
|
|
40
|
+
info.languageServiceHost.getCompilationSettings = () => {
|
|
41
|
+
const settings = { ...getCompilationSettings() };
|
|
42
|
+
if (settings.rootDirs) {
|
|
43
|
+
// TODO: If the `dtsOutDir` is not in `rootDirs`, warn the user.
|
|
44
|
+
settings.rootDirs = settings.rootDirs.filter((dir) => dir !== config.dtsOutDir);
|
|
45
|
+
}
|
|
46
|
+
return settings;
|
|
47
|
+
};
|
|
48
|
+
|
|
36
49
|
const moduleResolutionCache = info.languageServiceHost.getModuleResolutionCache?.();
|
|
37
50
|
const resolver = createResolver(config.compilerOptions, moduleResolutionCache);
|
|
38
51
|
const matchesPattern = createMatchesPattern(config);
|
|
39
52
|
|
|
40
53
|
return {
|
|
41
|
-
languagePlugins: [createCSSLanguagePlugin(resolver, matchesPattern)],
|
|
54
|
+
languagePlugins: [createCSSLanguagePlugin(resolver, matchesPattern, config)],
|
|
42
55
|
setup: (language) => {
|
|
43
56
|
info.languageService = proxyLanguageService(
|
|
44
57
|
language,
|
|
@@ -46,6 +59,7 @@ const plugin = createLanguageServicePlugin((ts, info) => {
|
|
|
46
59
|
info.project,
|
|
47
60
|
resolver,
|
|
48
61
|
matchesPattern,
|
|
62
|
+
config,
|
|
49
63
|
);
|
|
50
64
|
},
|
|
51
65
|
};
|
package/src/language-plugin.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CSSModule, DiagnosticWithLocation, MatchesPattern, Resolver } from '@css-modules-kit/core';
|
|
1
|
+
import type { CMKConfig, CSSModule, DiagnosticWithLocation, MatchesPattern, Resolver } from '@css-modules-kit/core';
|
|
2
2
|
import { createDts, parseCSSModule } from '@css-modules-kit/core';
|
|
3
3
|
import type { LanguagePlugin, SourceScript, VirtualCode } from '@volar/language-core';
|
|
4
4
|
import type {} from '@volar/typescript';
|
|
@@ -24,6 +24,7 @@ export interface CSSModuleScript extends SourceScript<string> {
|
|
|
24
24
|
export function createCSSLanguagePlugin(
|
|
25
25
|
resolver: Resolver,
|
|
26
26
|
matchesPattern: MatchesPattern,
|
|
27
|
+
config: CMKConfig,
|
|
27
28
|
): LanguagePlugin<string, VirtualCode> {
|
|
28
29
|
return {
|
|
29
30
|
getLanguageId(scriptId) {
|
|
@@ -52,7 +53,12 @@ export function createCSSLanguagePlugin(
|
|
|
52
53
|
// So, ts-plugin uses a fault-tolerant Parser to parse CSS.
|
|
53
54
|
safe: true,
|
|
54
55
|
});
|
|
55
|
-
|
|
56
|
+
// eslint-disable-next-line prefer-const
|
|
57
|
+
let { text, mapping, linkedCodeMapping } = createDts(
|
|
58
|
+
cssModule,
|
|
59
|
+
{ resolver, matchesPattern },
|
|
60
|
+
{ ...config, forTsPlugin: true },
|
|
61
|
+
);
|
|
56
62
|
return {
|
|
57
63
|
id: 'main',
|
|
58
64
|
languageId: LANGUAGE_ID,
|
|
@@ -1,22 +1,39 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { CMKConfig, Resolver } from '@css-modules-kit/core';
|
|
2
|
+
import { isComponentFileName, isCSSModuleFile } from '@css-modules-kit/core';
|
|
2
3
|
import type { Language } from '@volar/language-core';
|
|
3
4
|
import ts from 'typescript';
|
|
4
5
|
import { isCSSModuleScript } from '../../language-plugin.js';
|
|
6
|
+
import { convertDefaultImportsToNamespaceImports, createPreferencesForCompletion } from '../../util.js';
|
|
5
7
|
|
|
6
|
-
// ref: https://github.com/microsoft/TypeScript/blob/220706eb0320ff46fad8bf80a5e99db624ee7dfb/src/compiler/diagnosticMessages.json
|
|
8
|
+
// ref: https://github.com/microsoft/TypeScript/blob/220706eb0320ff46fad8bf80a5e99db624ee7dfb/src/compiler/diagnosticMessages.json
|
|
9
|
+
export const CANNOT_FIND_NAME_ERROR_CODE = 2304;
|
|
7
10
|
export const PROPERTY_DOES_NOT_EXIST_ERROR_CODE = 2339;
|
|
8
11
|
|
|
9
12
|
export function getCodeFixesAtPosition(
|
|
10
13
|
language: Language<string>,
|
|
11
14
|
languageService: ts.LanguageService,
|
|
12
15
|
project: ts.server.Project,
|
|
16
|
+
resolver: Resolver,
|
|
17
|
+
config: CMKConfig,
|
|
13
18
|
): ts.LanguageService['getCodeFixesAtPosition'] {
|
|
14
19
|
// eslint-disable-next-line max-params
|
|
15
20
|
return (fileName, start, end, errorCodes, formatOptions, preferences) => {
|
|
16
21
|
const prior = Array.from(
|
|
17
|
-
languageService.getCodeFixesAtPosition(
|
|
22
|
+
languageService.getCodeFixesAtPosition(
|
|
23
|
+
fileName,
|
|
24
|
+
start,
|
|
25
|
+
end,
|
|
26
|
+
errorCodes,
|
|
27
|
+
formatOptions,
|
|
28
|
+
createPreferencesForCompletion(preferences, config),
|
|
29
|
+
),
|
|
18
30
|
);
|
|
19
31
|
|
|
32
|
+
if (config.namedExports && !config.prioritizeNamedImports) {
|
|
33
|
+
convertDefaultImportsToNamespaceImports(prior, fileName, resolver);
|
|
34
|
+
excludeNamedImports(prior, fileName, resolver);
|
|
35
|
+
}
|
|
36
|
+
|
|
20
37
|
if (isComponentFileName(fileName)) {
|
|
21
38
|
// If a user is trying to use a non-existent token (e.g. `styles.nonExistToken`), provide a code fix to add the token.
|
|
22
39
|
if (errorCodes.includes(PROPERTY_DOES_NOT_EXIST_ERROR_CODE)) {
|
|
@@ -31,10 +48,29 @@ export function getCodeFixesAtPosition(
|
|
|
31
48
|
}
|
|
32
49
|
}
|
|
33
50
|
|
|
34
|
-
return prior;
|
|
51
|
+
return prior.filter((codeFix) => codeFix.changes.length > 0);
|
|
35
52
|
};
|
|
36
53
|
}
|
|
37
54
|
|
|
55
|
+
/**
|
|
56
|
+
* Exclude code fixes that add named imports (e.g. `import { foo } from './a.module.css'`)
|
|
57
|
+
*/
|
|
58
|
+
function excludeNamedImports(codeFixes: ts.CodeFixAction[], fileName: string, resolver: Resolver): void {
|
|
59
|
+
for (const codeFix of codeFixes) {
|
|
60
|
+
if (codeFix.fixName !== 'import') continue;
|
|
61
|
+
const match = codeFix.description.match(/^Add import from "(.*)"$/u);
|
|
62
|
+
if (!match) continue;
|
|
63
|
+
const specifier = match[1]!;
|
|
64
|
+
const resolved = resolver(specifier, { request: fileName });
|
|
65
|
+
if (!resolved || !isCSSModuleFile(resolved)) continue;
|
|
66
|
+
|
|
67
|
+
for (const change of codeFix.changes) {
|
|
68
|
+
change.textChanges = change.textChanges.filter((textChange) => !textChange.newText.startsWith(`import {`));
|
|
69
|
+
}
|
|
70
|
+
codeFix.changes = codeFix.changes.filter((change) => change.textChanges.length > 0);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
38
74
|
interface TokenConsumer {
|
|
39
75
|
/** The token name (e.g. `foo` in `styles.foo`) */
|
|
40
76
|
tokenName: string;
|
|
@@ -1,16 +1,26 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { CMKConfig, Resolver } from '@css-modules-kit/core';
|
|
2
|
+
import { getCssModuleFileName, isComponentFileName, isCSSModuleFile, STYLES_EXPORT_NAME } from '@css-modules-kit/core';
|
|
2
3
|
import ts from 'typescript';
|
|
4
|
+
import { convertDefaultImportsToNamespaceImports, createPreferencesForCompletion } from '../../util.js';
|
|
3
5
|
|
|
4
6
|
export function getCompletionsAtPosition(
|
|
5
7
|
languageService: ts.LanguageService,
|
|
8
|
+
config: CMKConfig,
|
|
6
9
|
): ts.LanguageService['getCompletionsAtPosition'] {
|
|
7
10
|
return (fileName, position, options, formattingSettings) => {
|
|
8
|
-
const prior = languageService.getCompletionsAtPosition(
|
|
11
|
+
const prior = languageService.getCompletionsAtPosition(
|
|
12
|
+
fileName,
|
|
13
|
+
position,
|
|
14
|
+
createPreferencesForCompletion(options ?? {}, config),
|
|
15
|
+
formattingSettings,
|
|
16
|
+
);
|
|
9
17
|
|
|
10
|
-
if (
|
|
18
|
+
if (!prior) return;
|
|
19
|
+
|
|
20
|
+
if (isComponentFileName(fileName)) {
|
|
11
21
|
const cssModuleFileName = getCssModuleFileName(fileName);
|
|
12
22
|
for (const entry of prior.entries) {
|
|
13
|
-
if (
|
|
23
|
+
if (isDefaultExportedStylesEntry(entry) && entry.data.fileName === cssModuleFileName) {
|
|
14
24
|
// Prioritize the completion of the `styles' import for the current .ts file for usability.
|
|
15
25
|
// NOTE: This is a hack to make the completion item appear at the top
|
|
16
26
|
entry.sortText = '0';
|
|
@@ -20,21 +30,52 @@ export function getCompletionsAtPosition(
|
|
|
20
30
|
}
|
|
21
31
|
}
|
|
22
32
|
}
|
|
33
|
+
if (config.namedExports && !config.prioritizeNamedImports) {
|
|
34
|
+
// When `namedExports` is enabled, you can write code as follows:
|
|
35
|
+
// ```tsx
|
|
36
|
+
// import { button } from './a.module.css';
|
|
37
|
+
// const Button = () => <button className={button}>Click me!</button>;
|
|
38
|
+
// ```
|
|
39
|
+
// However, it is more common to use namespace imports for styles.
|
|
40
|
+
// ```tsx
|
|
41
|
+
// import * as styles from './a.module.css';
|
|
42
|
+
// const Button = () => <button className={styles.button}>Click me!</button>;
|
|
43
|
+
// ```
|
|
44
|
+
// Therefore, completion for tokens like `button` is disabled.
|
|
45
|
+
prior.entries = prior.entries.filter((entry) => !isNamedExportedTokenEntry(entry));
|
|
46
|
+
}
|
|
23
47
|
return prior;
|
|
24
48
|
};
|
|
25
49
|
}
|
|
26
50
|
|
|
51
|
+
type DefaultExportedStylesEntry = ts.CompletionEntry & {
|
|
52
|
+
data: ts.CompletionEntryData;
|
|
53
|
+
};
|
|
54
|
+
|
|
27
55
|
/**
|
|
28
|
-
* Check if the completion entry is the `styles` entry
|
|
56
|
+
* Check if the completion entry is the default exported `styles` entry.
|
|
29
57
|
*/
|
|
30
|
-
function
|
|
58
|
+
function isDefaultExportedStylesEntry(entry: ts.CompletionEntry): entry is DefaultExportedStylesEntry {
|
|
31
59
|
return (
|
|
32
60
|
entry.name === STYLES_EXPORT_NAME &&
|
|
33
|
-
entry.data &&
|
|
61
|
+
entry.data !== undefined &&
|
|
34
62
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison
|
|
35
63
|
entry.data.exportName === ts.InternalSymbolName.Default &&
|
|
36
|
-
entry.data.fileName &&
|
|
37
|
-
entry.data.fileName
|
|
64
|
+
entry.data.fileName !== undefined &&
|
|
65
|
+
isCSSModuleFile(entry.data.fileName)
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Check if the completion entry is a named exported token entry.
|
|
71
|
+
*/
|
|
72
|
+
function isNamedExportedTokenEntry(entry: ts.CompletionEntry): boolean {
|
|
73
|
+
return (
|
|
74
|
+
entry.data !== undefined &&
|
|
75
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison
|
|
76
|
+
entry.data.exportName !== ts.InternalSymbolName.Default &&
|
|
77
|
+
entry.data.fileName !== undefined &&
|
|
78
|
+
isCSSModuleFile(entry.data.fileName)
|
|
38
79
|
);
|
|
39
80
|
}
|
|
40
81
|
|
|
@@ -46,3 +87,28 @@ function isClassNamePropEntry(entry: ts.CompletionEntry) {
|
|
|
46
87
|
entry.isSnippet
|
|
47
88
|
);
|
|
48
89
|
}
|
|
90
|
+
|
|
91
|
+
export function getCompletionEntryDetails(
|
|
92
|
+
languageService: ts.LanguageService,
|
|
93
|
+
resolver: Resolver,
|
|
94
|
+
config: CMKConfig,
|
|
95
|
+
): ts.LanguageService['getCompletionEntryDetails'] {
|
|
96
|
+
// eslint-disable-next-line max-params
|
|
97
|
+
return (fileName, position, entryName, formatOptions, source, preferences, data) => {
|
|
98
|
+
const details = languageService.getCompletionEntryDetails(
|
|
99
|
+
fileName,
|
|
100
|
+
position,
|
|
101
|
+
entryName,
|
|
102
|
+
formatOptions,
|
|
103
|
+
source,
|
|
104
|
+
preferences,
|
|
105
|
+
data,
|
|
106
|
+
);
|
|
107
|
+
if (!details) return undefined;
|
|
108
|
+
|
|
109
|
+
if (config.namedExports && !config.prioritizeNamedImports && details.codeActions) {
|
|
110
|
+
convertDefaultImportsToNamespaceImports(details.codeActions, fileName, resolver);
|
|
111
|
+
}
|
|
112
|
+
return details;
|
|
113
|
+
};
|
|
114
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Language } from '@volar/language-core';
|
|
2
|
+
import type ts from 'typescript';
|
|
3
|
+
import { CMK_DATA_KEY, isCSSModuleScript } from '../../language-plugin.js';
|
|
4
|
+
|
|
5
|
+
export function getDefinitionAndBoundSpan(
|
|
6
|
+
language: Language<string>,
|
|
7
|
+
languageService: ts.LanguageService,
|
|
8
|
+
): ts.LanguageService['getDefinitionAndBoundSpan'] {
|
|
9
|
+
return (...args) => {
|
|
10
|
+
const result = languageService.getDefinitionAndBoundSpan(...args);
|
|
11
|
+
if (!result) return;
|
|
12
|
+
if (!result.definitions) return result;
|
|
13
|
+
for (const def of result.definitions) {
|
|
14
|
+
const script = language.scripts.get(def.fileName);
|
|
15
|
+
if (isCSSModuleScript(script)) {
|
|
16
|
+
const cssModule = script.generated.root[CMK_DATA_KEY].cssModule;
|
|
17
|
+
const token = cssModule.localTokens.find((t) => t.name === def.name);
|
|
18
|
+
if (token?.declarationLoc) {
|
|
19
|
+
def.contextSpan = {
|
|
20
|
+
start: token.declarationLoc.start.offset,
|
|
21
|
+
length: token.declarationLoc.end.offset - token.declarationLoc.start.offset,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return result;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
@@ -1,19 +1,23 @@
|
|
|
1
|
+
import type { CMKConfig } from '@css-modules-kit/core';
|
|
1
2
|
import { createExportBuilder, type MatchesPattern, type Resolver } from '@css-modules-kit/core';
|
|
2
3
|
import type { Language } from '@volar/language-core';
|
|
3
4
|
import type ts from 'typescript';
|
|
4
5
|
import { CMK_DATA_KEY, isCSSModuleScript } from '../language-plugin.js';
|
|
5
6
|
import { getCodeFixesAtPosition } from './feature/code-fix.js';
|
|
6
|
-
import { getCompletionsAtPosition } from './feature/completion.js';
|
|
7
|
+
import { getCompletionEntryDetails, getCompletionsAtPosition } from './feature/completion.js';
|
|
8
|
+
import { getDefinitionAndBoundSpan } from './feature/definition-and-bound-span.js';
|
|
7
9
|
import { getApplicableRefactors, getEditsForRefactor } from './feature/refactor.js';
|
|
8
10
|
import { getSemanticDiagnostics } from './feature/semantic-diagnostic.js';
|
|
9
11
|
import { getSyntacticDiagnostics } from './feature/syntactic-diagnostic.js';
|
|
10
12
|
|
|
13
|
+
// eslint-disable-next-line max-params
|
|
11
14
|
export function proxyLanguageService(
|
|
12
15
|
language: Language<string>,
|
|
13
16
|
languageService: ts.LanguageService,
|
|
14
17
|
project: ts.server.Project,
|
|
15
18
|
resolver: Resolver,
|
|
16
19
|
matchesPattern: MatchesPattern,
|
|
20
|
+
config: CMKConfig,
|
|
17
21
|
): ts.LanguageService {
|
|
18
22
|
const proxy: ts.LanguageService = Object.create(null);
|
|
19
23
|
|
|
@@ -44,8 +48,10 @@ export function proxyLanguageService(
|
|
|
44
48
|
);
|
|
45
49
|
proxy.getApplicableRefactors = getApplicableRefactors(languageService, project);
|
|
46
50
|
proxy.getEditsForRefactor = getEditsForRefactor(languageService);
|
|
47
|
-
proxy.getCompletionsAtPosition = getCompletionsAtPosition(languageService);
|
|
48
|
-
proxy.
|
|
51
|
+
proxy.getCompletionsAtPosition = getCompletionsAtPosition(languageService, config);
|
|
52
|
+
proxy.getCompletionEntryDetails = getCompletionEntryDetails(languageService, resolver, config);
|
|
53
|
+
proxy.getCodeFixesAtPosition = getCodeFixesAtPosition(language, languageService, project, resolver, config);
|
|
54
|
+
proxy.getDefinitionAndBoundSpan = getDefinitionAndBoundSpan(language, languageService);
|
|
49
55
|
|
|
50
56
|
return proxy;
|
|
51
57
|
}
|
package/src/util.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type CMKConfig, isCSSModuleFile, type Resolver, STYLES_EXPORT_NAME } from '@css-modules-kit/core';
|
|
1
2
|
import ts from 'typescript';
|
|
2
3
|
|
|
3
4
|
/** The error code used by tsserver to display the css-modules-kit error in the editor. */
|
|
@@ -17,3 +18,41 @@ export function convertErrorCategory(category: 'error' | 'warning' | 'suggestion
|
|
|
17
18
|
throw new Error(`Unknown category: ${String(category)}`);
|
|
18
19
|
}
|
|
19
20
|
}
|
|
21
|
+
|
|
22
|
+
export function createPreferencesForCompletion<T extends ts.UserPreferences>(preferences: T, config: CMKConfig): T {
|
|
23
|
+
// By default, files in `generated/` are included in the completion candidates.
|
|
24
|
+
// To exclude them, we add the `dtsOutDir` to the `autoImportFileExcludePatterns`.
|
|
25
|
+
return {
|
|
26
|
+
...preferences,
|
|
27
|
+
autoImportFileExcludePatterns: [...(preferences.autoImportFileExcludePatterns ?? []), config.dtsOutDir],
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Convert default imports to namespace imports for CSS modules.
|
|
32
|
+
* For example, convert `import styles from './styles.module.css'` to `import * as styles from './styles.module.css'`.
|
|
33
|
+
*/
|
|
34
|
+
export function convertDefaultImportsToNamespaceImports(
|
|
35
|
+
codeFixes: ts.CodeFixAction[] | ts.CodeAction[],
|
|
36
|
+
fileName: string,
|
|
37
|
+
resolver: Resolver,
|
|
38
|
+
): void {
|
|
39
|
+
for (const codeFix of codeFixes) {
|
|
40
|
+
if ('fixName' in codeFix && codeFix.fixName !== 'import') continue;
|
|
41
|
+
// Check if the code fix is to add an import for a CSS module.
|
|
42
|
+
const match = codeFix.description.match(/^Add import from "(.*)"$/u);
|
|
43
|
+
if (!match) continue;
|
|
44
|
+
const specifier = match[1]!;
|
|
45
|
+
const resolved = resolver(specifier, { request: fileName });
|
|
46
|
+
if (!resolved || !isCSSModuleFile(resolved)) continue;
|
|
47
|
+
|
|
48
|
+
// If the specifier is a CSS module, convert the import to a namespace import.
|
|
49
|
+
for (const change of codeFix.changes) {
|
|
50
|
+
for (const textChange of change.textChanges) {
|
|
51
|
+
textChange.newText = textChange.newText.replace(
|
|
52
|
+
`import ${STYLES_EXPORT_NAME} from`,
|
|
53
|
+
`import * as ${STYLES_EXPORT_NAME} from`,
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|