Skip to content

Commit 7c6696a

Browse files
refactor: cleanup dependencies relationship (#5421)
1 parent c5e889b commit 7c6696a

32 files changed

+406
-624
lines changed

extensions/vscode/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,7 @@
470470
"@types/vscode": "^1.82.0",
471471
"@volar/vscode": "~2.4.14",
472472
"@vscode/vsce": "^3.2.1",
473-
"@vue/language-core": "3.0.0-alpha.10",
473+
"@vue/compiler-sfc": "^3.5.0",
474474
"@vue/language-server": "3.0.0-alpha.10",
475475
"@vue/typescript-plugin": "3.0.0-alpha.10",
476476
"reactive-vscode": "^0.2.9",

extensions/vscode/rolldown.config.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,12 @@ const config: RolldownOptions = {
2828
name: 'redirect',
2929
buildEnd() {
3030
fs.mkdirSync(resolve('./node_modules/vue-typescript-plugin-pack'), { recursive: true });
31-
fs.writeFileSync(resolve('./node_modules/vue-typescript-plugin-pack/index.js'), `module.exports = require('../../dist/plugin.js');`);
31+
fs.writeFileSync(resolve('./node_modules/vue-typescript-plugin-pack/index.js'), `module.exports = require('../../dist/typescript-plugin.js');`);
3232

3333
if (isDev) {
3434
fs.mkdirSync(resolve('./dist'), { recursive: true });
35-
fs.writeFileSync(resolve('./dist/server.js'), `module.exports = require('../node_modules/@vue/language-server/node.js');`);
36-
fs.writeFileSync(resolve('./dist/plugin.js'), `module.exports = require('../node_modules/@vue/typescript-plugin/index.js');`);
35+
fs.writeFileSync(resolve('./dist/language-server.js'), `module.exports = require('../node_modules/@vue/language-server/index.js');`);
36+
fs.writeFileSync(resolve('./dist/typescript-plugin.js'), `module.exports = require('../node_modules/@vue/typescript-plugin/index.js');`);
3737
}
3838
},
3939
},
@@ -68,8 +68,8 @@ const config: RolldownOptions = {
6868
if (!isDev) {
6969
config.input = {
7070
...config.input as Record<string, string>,
71-
'server': './node_modules/@vue/language-server/node.js',
72-
'plugin': './node_modules/@vue/typescript-plugin/index.js',
71+
'language-server': './node_modules/@vue/language-server/index.js',
72+
'typescript-plugin': './node_modules/@vue/typescript-plugin/index.js',
7373
};
7474
}
7575

extensions/vscode/src/features/splitEditors.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
import { ExecuteCommandRequest, type BaseLanguageClient, type ExecuteCommandParams } from '@volar/vscode';
2-
import type { SFCParseResult } from '@vue/language-server';
3-
import { commands } from '@vue/language-server/lib/types';
2+
import type { SFCBlock, SFCParseResult } from '@vue/compiler-sfc';
43
import { executeCommand, useActiveTextEditor, useCommand } from 'reactive-vscode';
54
import * as vscode from 'vscode';
65
import { config } from '../config';
76

8-
type SFCBlock = SFCParseResult['descriptor']['customBlocks'][number];
9-
107
export function activate(client: BaseLanguageClient) {
118

129
const activeTextEditor = useActiveTextEditor();
@@ -109,7 +106,7 @@ export function useDocDescriptor(client: BaseLanguageClient) {
109106
if (text !== splitDocText) {
110107
splitDocText = text;
111108
splitDocDescriptor = await client.sendRequest(ExecuteCommandRequest.type, {
112-
command: commands.parseSfc,
109+
command: 'vue.parseSfc',
113110
arguments: [text],
114111
} satisfies ExecuteCommandParams);
115112
}

extensions/vscode/src/languageClient.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ async function activateLc(
6161
const selectors = config.server.includeLanguages;
6262

6363
// Setup typescript.js in production mode
64-
if (fs.existsSync(path.join(__dirname, 'server.js'))) {
64+
if (fs.existsSync(path.join(__dirname, 'language-server.js'))) {
6565
fs.writeFileSync(path.join(__dirname, 'typescript.js'), `module.exports = require("${vscode.env.appRoot.replace(/\\/g, '/')}/extensions/node_modules/typescript/lib/typescript.js");`);
6666
}
6767

extensions/vscode/src/nodeClientMain.ts

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -48,34 +48,31 @@ export const { activate, deactivate } = defineExtension(async () => {
4848
}
4949
}
5050

51-
let serverModule = vscode.Uri.joinPath(context.extensionUri, 'dist', 'server.js');
52-
53-
const serverOptions: lsp.ServerOptions = {
54-
run: {
55-
module: serverModule.fsPath,
56-
transport: lsp.TransportKind.ipc,
57-
options: {},
58-
},
59-
debug: {
60-
module: serverModule.fsPath,
61-
transport: lsp.TransportKind.ipc,
62-
options: { execArgv: ['--nolazy', '--inspect=' + port] },
63-
}
64-
};
65-
const clientOptions: lsp.LanguageClientOptions = {
66-
middleware,
67-
documentSelector: documentSelector,
68-
markdown: {
69-
isTrusted: true,
70-
supportHtml: true
71-
},
72-
outputChannel
73-
};
51+
const serverModule = vscode.Uri.joinPath(context.extensionUri, 'dist', 'language-server.js');
7452
const client = new _LanguageClient(
7553
id,
7654
name,
77-
serverOptions,
78-
clientOptions
55+
{
56+
run: {
57+
module: serverModule.fsPath,
58+
transport: lsp.TransportKind.ipc,
59+
options: {},
60+
},
61+
debug: {
62+
module: serverModule.fsPath,
63+
transport: lsp.TransportKind.ipc,
64+
options: { execArgv: ['--nolazy', '--inspect=' + port] },
65+
}
66+
},
67+
{
68+
middleware,
69+
documentSelector: documentSelector,
70+
markdown: {
71+
isTrusted: true,
72+
supportHtml: true
73+
},
74+
outputChannel
75+
}
7976
);
8077
client.start();
8178

packages/component-meta/package.json

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,6 @@
2121
"peerDependencies": {
2222
"typescript": "*"
2323
},
24-
"peerDependenciesMeta": {
25-
"typescript": {
26-
"optional": true
27-
}
28-
},
2924
"devDependencies": {
3025
"@types/node": "^22.10.4",
3126
"@types/path-browserify": "^1.0.1"

packages/language-core/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
export * from './lib/codegen/globalTypes';
22
export * from './lib/codegen/template';
3+
export * from './lib/codegen/utils';
34
export * from './lib/languagePlugin';
45
export * from './lib/parsers/scriptSetupRanges';
56
export * from './lib/plugins';
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
#!/usr/bin/env node
2-
// @ts-check
2+
33
if (process.argv.includes('--version')) {
44
console.log(require('../package.json').version);
5+
return;
56
}
6-
else {
7-
require('../node.js');
8-
}
7+
8+
require('../index.js');

packages/language-server/index.ts

Lines changed: 186 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,188 @@
1-
export * from './lib/types';
1+
import type { LanguageServer } from '@volar/language-server';
2+
import { createLanguageServiceEnvironment } from '@volar/language-server/lib/project/simpleProject';
3+
import { createConnection, createServer } from '@volar/language-server/node';
4+
import { createLanguage, createParsedCommandLine, createVueLanguagePlugin, getDefaultCompilerOptions } from '@vue/language-core';
5+
import { createLanguageService, createUriMap, createVueLanguageServicePlugins, type LanguageService } from '@vue/language-service';
6+
import * as ts from 'typescript';
7+
import { URI } from 'vscode-uri';
28

3-
// export types of parent package
4-
export * from '@volar/language-server/lib/types';
9+
const connection = createConnection();
10+
const server = createServer(connection);
511

6-
// only export types of depend packages
7-
export * from '@vue/language-service/lib/types';
12+
connection.listen();
13+
14+
connection.onInitialize(params => {
15+
const tsconfigProjects = createUriMap<LanguageService>();
16+
const file2ProjectInfo = new Map<string, Promise<ts.server.protocol.ProjectInfo | null>>();
17+
18+
server.fileWatcher.onDidChangeWatchedFiles(({ changes }) => {
19+
for (const change of changes) {
20+
const changeUri = URI.parse(change.uri);
21+
if (tsconfigProjects.has(changeUri)) {
22+
tsconfigProjects.get(changeUri)!.dispose();
23+
tsconfigProjects.delete(changeUri);
24+
file2ProjectInfo.clear();
25+
}
26+
}
27+
});
28+
29+
let simpleLs: LanguageService | undefined;
30+
let tsserverRequestId = 0;
31+
32+
const tsserverRequestHandlers = new Map<number, (res: any) => void>();
33+
34+
connection.onNotification('tsserver/response', ([id, res]) => {
35+
tsserverRequestHandlers.get(id)?.(res);
36+
tsserverRequestHandlers.delete(id);
37+
});
38+
39+
return server.initialize(
40+
params,
41+
{
42+
setup() { },
43+
async getLanguageService(uri) {
44+
if (uri.scheme === 'file') {
45+
const fileName = uri.fsPath.replace(/\\/g, '/');
46+
let projectInfoPromise = file2ProjectInfo.get(fileName);
47+
if (!projectInfoPromise) {
48+
projectInfoPromise = sendTsRequest<ts.server.protocol.ProjectInfo>(
49+
ts.server.protocol.CommandTypes.ProjectInfo,
50+
{
51+
file: fileName,
52+
needFileNameList: false,
53+
} satisfies ts.server.protocol.ProjectInfoRequestArgs
54+
);
55+
file2ProjectInfo.set(fileName, projectInfoPromise);
56+
}
57+
const projectInfo = await projectInfoPromise;
58+
if (projectInfo) {
59+
const { configFileName } = projectInfo;
60+
let ls = tsconfigProjects.get(URI.file(configFileName));
61+
if (!ls) {
62+
ls = createLs(server, configFileName);
63+
tsconfigProjects.set(URI.file(configFileName), ls);
64+
}
65+
return ls;
66+
}
67+
}
68+
return simpleLs ??= createLs(server, undefined);
69+
},
70+
getExistingLanguageServices() {
71+
return Promise.all([
72+
...tsconfigProjects.values(),
73+
simpleLs,
74+
].filter(promise => !!promise));
75+
},
76+
reload() {
77+
for (const ls of tsconfigProjects.values()) {
78+
ls.dispose();
79+
}
80+
tsconfigProjects.clear();
81+
if (simpleLs) {
82+
simpleLs.dispose();
83+
simpleLs = undefined;
84+
}
85+
},
86+
},
87+
createVueLanguageServicePlugins(ts, {
88+
collectExtractProps(...args) {
89+
return sendTsRequest('vue:collectExtractProps', args);
90+
},
91+
getComponentDirectives(...args) {
92+
return sendTsRequest('vue:getComponentDirectives', args);
93+
},
94+
getComponentEvents(...args) {
95+
return sendTsRequest('vue:getComponentEvents', args);
96+
},
97+
getComponentNames(...args) {
98+
return sendTsRequest('vue:getComponentNames', args);
99+
},
100+
getComponentProps(...args) {
101+
return sendTsRequest('vue:getComponentProps', args);
102+
},
103+
getElementAttrs(...args) {
104+
return sendTsRequest('vue:getElementAttrs', args);
105+
},
106+
getElementNames(...args) {
107+
return sendTsRequest('vue:getElementNames', args);
108+
},
109+
getImportPathForFile(...args) {
110+
return sendTsRequest('vue:getImportPathForFile', args);
111+
},
112+
getPropertiesAtLocation(...args) {
113+
return sendTsRequest('vue:getPropertiesAtLocation', args);
114+
},
115+
getDocumentHighlights(fileName, position) {
116+
return sendTsRequest(
117+
'documentHighlights-full', // internal command
118+
{
119+
file: fileName,
120+
...{ position } as unknown as { line: number; offset: number; },
121+
filesToSearch: [fileName],
122+
} satisfies ts.server.protocol.DocumentHighlightsRequestArgs
123+
);
124+
},
125+
async getQuickInfoAtPosition(fileName, { line, character }) {
126+
const result = await sendTsRequest<ts.QuickInfo>(
127+
ts.server.protocol.CommandTypes.Quickinfo,
128+
{
129+
file: fileName,
130+
line: line + 1,
131+
offset: character + 1,
132+
} satisfies ts.server.protocol.FileLocationRequestArgs
133+
);
134+
return ts.displayPartsToString(result?.displayParts ?? []);
135+
},
136+
})
137+
);
138+
139+
async function sendTsRequest<T>(command: string, args: any): Promise<T | null> {
140+
return await new Promise<T | null>(resolve => {
141+
const requestId = ++tsserverRequestId;
142+
tsserverRequestHandlers.set(requestId, resolve);
143+
connection.sendNotification('tsserver/request', [requestId, command, args]);
144+
});
145+
}
146+
147+
function createLs(server: LanguageServer, tsconfig: string | undefined) {
148+
const commonLine = tsconfig
149+
? createParsedCommandLine(ts, ts.sys, tsconfig)
150+
: {
151+
options: ts.getDefaultCompilerOptions(),
152+
vueOptions: getDefaultCompilerOptions(),
153+
};
154+
const language = createLanguage<URI>(
155+
[
156+
{
157+
getLanguageId: uri => server.documents.get(uri)?.languageId,
158+
},
159+
createVueLanguagePlugin(
160+
ts,
161+
commonLine.options,
162+
commonLine.vueOptions,
163+
uri => uri.fsPath.replace(/\\/g, '/')
164+
),
165+
],
166+
createUriMap(),
167+
uri => {
168+
const document = server.documents.get(uri);
169+
if (document) {
170+
language.scripts.set(uri, document.getSnapshot(), document.languageId);
171+
}
172+
else {
173+
language.scripts.delete(uri);
174+
}
175+
}
176+
);
177+
return createLanguageService(
178+
language,
179+
server.languageServicePlugins,
180+
createLanguageServiceEnvironment(server, [...server.workspaceFolders.all]),
181+
{ vue: { compilerOptions: commonLine.vueOptions } }
182+
);
183+
}
184+
});
185+
186+
connection.onInitialized(server.initialized);
187+
188+
connection.onShutdown(server.shutdown);

packages/language-server/lib/types.ts

Lines changed: 0 additions & 3 deletions
This file was deleted.

0 commit comments

Comments
 (0)