/
common.ts
126 lines (105 loc) · 3.9 KB
/
common.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import * as vue from '@volar/vue-language-service';
import * as vscode from 'vscode-languageserver';
import { URI } from 'vscode-uri';
import { LanguageConfigs, RuntimeEnvironment, ServerInitializationOptions } from './types';
import { createConfigurationHost } from './utils/configurationHost';
import { createSnapshots } from './utils/snapshots';
import { createWorkspaces } from './utils/workspaces';
export function createLanguageServer(
connection: vscode.Connection,
runtimeEnv: RuntimeEnvironment,
languageConfigs: LanguageConfigs = {
definitelyExts: ['.vue'],
indeterminateExts: ['.md', '.html'],
getDocumentService: vue.getDocumentService,
createLanguageService: vue.createLanguageService,
},
) {
let params: vscode.InitializeParams;
let options: ServerInitializationOptions;
let roots: URI[] = [];
connection.onInitialize(async _params => {
params = _params;
options = params.initializationOptions as any;
if (params.capabilities.workspace?.workspaceFolders && params.workspaceFolders) {
roots = params.workspaceFolders.map(folder => URI.parse(folder.uri));
}
else if (params.rootUri) {
roots = [URI.parse(params.rootUri)];
}
else if (params.rootPath) {
roots = [URI.file(params.rootPath)];
}
const result: vscode.InitializeResult = {
capabilities: {
textDocumentSync: (options.textDocumentSync as vscode.TextDocumentSyncKind) ?? vscode.TextDocumentSyncKind.Incremental,
},
};
if (options.documentFeatures) {
(await import('./registers/registerDocumentFeatures')).register(options.documentFeatures, result.capabilities);
}
if (options.languageFeatures) {
(await import('./registers/registerlanguageFeatures')).register(options.languageFeatures!, vue.getSemanticTokenLegend(), result.capabilities, languageConfigs);
}
return result;
});
connection.onInitialized(async () => {
const configHost = params.capabilities.workspace?.configuration ? createConfigurationHost(roots, connection) : undefined;
const ts = runtimeEnv.loadTypescript(options);
if (options.documentFeatures) {
const documentService = languageConfigs.getDocumentService(
ts,
configHost,
runtimeEnv.fileSystemProvide,
loadCustomPlugins(roots[0].fsPath), // TODO: handle multiple roots
roots[0],
);
(await import('./features/documentFeatures')).register(connection, documents, documentService, options.documentFeatures.allowedLanguageIds);
}
if (options.languageFeatures) {
const fsHost = runtimeEnv.createFileSystemHost(ts, connection, params.capabilities);
const tsLocalized = runtimeEnv.loadTypescriptLocalized(options);
const projects = createWorkspaces(
runtimeEnv,
languageConfigs,
fsHost,
configHost,
ts,
tsLocalized,
options,
documents,
connection,
);
for (const root of roots) {
projects.add(root);
}
(await import('./features/customFeatures')).register(connection, projects);
(await import('./features/languageFeatures')).register(connection, projects, options.languageFeatures, params);
connection.workspace.onDidChangeWorkspaceFolders(e => {
for (const folder of e.added) {
projects.add(URI.parse(folder.uri));
}
for (const folder of e.removed) {
projects.remove(URI.parse(folder.uri));
}
});
}
if (params.capabilities.workspace?.didChangeConfiguration?.dynamicRegistration) { // TODO
connection.client.register(vscode.DidChangeConfigurationNotification.type);
}
});
connection.listen();
const documents = createSnapshots(connection);
}
export function loadCustomPlugins(dir: string) {
try {
const configPath = require.resolve('./volar.config.js', { paths: [dir] });
const config: { plugins?: vue.EmbeddedLanguageServicePlugin[]; } = require(configPath);
// console.warn('Found', configPath, 'and loaded', config.plugins?.length, 'plugins.');
return config.plugins ?? [];
}
catch (err) {
// console.warn('No volar.config.js found in', dir);
return [];
}
}