/
common.ts
126 lines (109 loc) · 4.48 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 shared from '@volar/shared';
import { TextDocument } from 'vscode-languageserver-textdocument';
import * as vscode from 'vscode-languageserver';
import { URI } from 'vscode-uri';
import * as vue from '@volar/vue-language-service';
import { createLsConfigs } from './configHost';
import { getInferredCompilerOptions } from './inferredCompilerOptions';
import { createProjects } from './projects';
import type { FileSystemProvider } from 'vscode-html-languageservice';
export interface RuntimeEnvironment {
loadTypescript: (initOptions: shared.ServerInitializationOptions) => typeof import('typescript/lib/tsserverlibrary'),
loadTypescriptLocalized: (initOptions: shared.ServerInitializationOptions) => any,
schemaRequestHandlers: { [schema: string]: (uri: string, encoding?: BufferEncoding) => Promise<string>; },
onDidChangeConfiguration?: (settings: any) => void,
fileSystemProvide: FileSystemProvider | undefined,
}
export interface LanguageConfigs {
definitelyExts: string[],
indeterminateExts: string[],
getDocumentService: typeof vue.getDocumentService,
createLanguageService: typeof vue.createLanguageService,
}
export function createLanguageServer(
connection: vscode.Connection,
runtimeEnv: RuntimeEnvironment,
languageConfigs: LanguageConfigs = {
definitelyExts: ['.vue'],
indeterminateExts: ['.md', '.html'],
getDocumentService: vue.getDocumentService,
createLanguageService: vue.createLanguageService,
},
) {
let clientCapabilities: vscode.ClientCapabilities;
connection.onInitialize(async params => {
const options: shared.ServerInitializationOptions = params.initializationOptions as any;
clientCapabilities = params.capabilities;
let folders: string[] = [];
let rootUri: URI;
if (params.capabilities.workspace?.workspaceFolders && params.workspaceFolders) {
folders = params.workspaceFolders
.map(folder => URI.parse(folder.uri))
.filter(uri => uri.scheme === 'file')
.map(uri => uri.fsPath);
}
else if (params.rootUri && (rootUri = URI.parse(params.rootUri)).scheme === 'file') {
folders = [rootUri.fsPath];
}
else if (params.rootPath) {
folders = [params.rootPath];
}
const result: vscode.InitializeResult = {
capabilities: {
textDocumentSync: vscode.TextDocumentSyncKind.Incremental,
},
};
const configuration = params.capabilities.workspace?.configuration ? connection.workspace : undefined;
const ts = runtimeEnv.loadTypescript(options);
const configHost = params.capabilities.workspace?.configuration ? createLsConfigs(folders, connection) : undefined;
if (options.documentFeatures) {
const documentService = languageConfigs.getDocumentService(
{ typescript: ts },
configHost,
runtimeEnv.fileSystemProvide,
loadCustomPlugins(folders[0]),
);
(await import('./features/documentFeatures')).register(connection, documents, documentService, options.documentFeatures.allowedLanguageIds);
(await import('./registers/registerDocumentFeatures')).register(options.documentFeatures, result.capabilities);
}
if (options.languageFeatures) {
const tsLocalized = runtimeEnv.loadTypescriptLocalized(options);
const projects = createProjects(
runtimeEnv,
languageConfigs,
folders,
ts,
tsLocalized,
options,
documents,
connection,
configHost,
() => getInferredCompilerOptions(ts, configuration),
);
(await import('./features/customFeatures')).register(connection, documents, projects);
(await import('./features/languageFeatures')).register(ts, connection, documents, projects, options.languageFeatures, params, languageConfigs);
(await import('./registers/registerlanguageFeatures')).register(options.languageFeatures!, vue.getSemanticTokenLegend(), result.capabilities, languageConfigs);
}
return result;
});
connection.onInitialized(() => {
if (clientCapabilities.workspace?.didChangeConfiguration?.dynamicRegistration) { // TODO
connection.client.register(vscode.DidChangeConfigurationNotification.type);
}
});
connection.listen();
const documents = new vscode.TextDocuments(TextDocument);
documents.listen(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 [];
}
}