Skip to content

Commit 9d8133d

Browse files
committed
feat: auto import
1 parent 486b247 commit 9d8133d

File tree

2 files changed

+71
-1
lines changed

2 files changed

+71
-1
lines changed

packages/language-server/src/index.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { createConnection, createServer, createTypeScriptProject, loadTsdkByPath } from "@volar/language-server/node";
22
import { create as createTypeScriptServices } from "volar-service-typescript";
33
import { createJsrsLanguagePlugin } from "./languagePlugin";
4+
import { proxyLanguageService } from "./proxy";
45
import { getLanguageServicePlugins } from "./service";
56

67
export { JsrsVirtualCode } from "./virtualCode";
@@ -22,7 +23,19 @@ connection.onInitialize((params) => {
2223
[
2324
...createTypeScriptServices(tsdk.typescript),
2425
...getLanguageServicePlugins(),
25-
],
26+
].map((plugin) => {
27+
if (plugin.name !== "typescript-semantic")
28+
return plugin;
29+
return {
30+
...plugin,
31+
create(context) {
32+
const created = plugin.create(context);
33+
const languageService = (created.provide as import("volar-service-typescript").Provide)["typescript/languageService"]();
34+
proxyLanguageService(languageService);
35+
return created;
36+
},
37+
};
38+
}),
2639
);
2740
});
2841

packages/language-server/src/proxy.ts

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Based on https://github.com/vuejs/language-tools/blob/master/packages/typescript-plugin/lib/common.ts
2+
3+
import type * as ts from "typescript";
4+
5+
const windowsPathReg = /\\/g;
6+
7+
export function proxyLanguageService(
8+
languageService: ts.LanguageService,
9+
) {
10+
languageService.getCompletionsAtPosition = getCompletionsAtPosition(languageService.getCompletionsAtPosition);
11+
languageService.getCompletionEntryDetails = getCompletionEntryDetails(languageService.getCompletionEntryDetails);
12+
languageService.getCodeFixesAtPosition = getCodeFixesAtPosition(languageService.getCodeFixesAtPosition);
13+
}
14+
15+
function getCompletionsAtPosition(getCompletionsAtPosition: ts.LanguageService["getCompletionsAtPosition"]): ts.LanguageService["getCompletionsAtPosition"] {
16+
return (filePath, position, options, formattingSettings) => {
17+
const fileName = filePath.replace(windowsPathReg, "/");
18+
const result = getCompletionsAtPosition(fileName, position, options, formattingSettings);
19+
if (result) {
20+
// filter __JSRS_
21+
result.entries = result.entries.filter(
22+
entry => !entry.name.includes("__JSRS_")
23+
&& !entry.labelDetails?.description?.includes("__JSRS_"),
24+
);
25+
}
26+
return result;
27+
};
28+
}
29+
30+
function getCompletionEntryDetails(getCompletionEntryDetails: ts.LanguageService["getCompletionEntryDetails"]): ts.LanguageService["getCompletionEntryDetails"] {
31+
return (filename, ...args) => {
32+
const details = getCompletionEntryDetails(filename, ...args);
33+
// modify import statement
34+
if (filename.endsWith(".jsrs")) {
35+
for (const codeAction of details?.codeActions ?? []) {
36+
for (const change of codeAction.changes) {
37+
for (const textChange of change.textChanges) {
38+
textChange.newText = textChange.newText.replace(
39+
/\bimport (.*) from (['"].*['"])/,
40+
(_, name, source) => `import!(${name} from ${source})`,
41+
);
42+
}
43+
}
44+
}
45+
}
46+
return details;
47+
};
48+
}
49+
50+
function getCodeFixesAtPosition(getCodeFixesAtPosition: ts.LanguageService["getCodeFixesAtPosition"]): ts.LanguageService["getCodeFixesAtPosition"] {
51+
return (...args) => {
52+
let result = getCodeFixesAtPosition(...args);
53+
// filter __JSRS_
54+
result = result.filter(entry => !entry.description.includes("__JSRS_"));
55+
return result;
56+
};
57+
}

0 commit comments

Comments
 (0)