forked from vuejs/language-tools
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinitialize.ts
107 lines (103 loc) · 4.3 KB
/
initialize.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
import type { LanguageServer } from '@volar/language-server';
import { createTypeScriptProject } from '@volar/language-server/node';
import { createParsedCommandLine, createVueLanguagePlugin, generateGlobalTypes, getAllExtensions, resolveGlobalTypesName, resolveVueCompilerOptions, VueCompilerOptions } from '@vue/language-core';
import { Disposable, getFullLanguageServicePlugins, InitializeParams } from '@vue/language-service';
import type * as ts from 'typescript';
export function initialize(
server: LanguageServer,
params: InitializeParams,
ts: typeof import('typescript'),
tsLocalized: ts.MapLike<string> | undefined
) {
const watchingExtensions = new Set<string>();
let fileWatcher: Promise<Disposable> | undefined;
return server.initialize(
params,
createTypeScriptProject(
ts,
tsLocalized,
async ({ configFileName, sys, uriConverter }) => {
let compilerOptions: ts.CompilerOptions;
let vueCompilerOptions: VueCompilerOptions;
if (configFileName) {
let commandLine = createParsedCommandLine(ts, sys, configFileName, true);
let sysVersion = sys.version;
let newSysVersion = await sys.sync();
while (sysVersion !== newSysVersion) {
commandLine = createParsedCommandLine(ts, sys, configFileName, true);
sysVersion = newSysVersion;
newSysVersion = await sys.sync();
}
compilerOptions = commandLine.options;
vueCompilerOptions = commandLine.vueOptions;
}
else {
compilerOptions = ts.getDefaultCompilerOptions();
vueCompilerOptions = resolveVueCompilerOptions({});
}
vueCompilerOptions.__test = params.initializationOptions.typescript.disableAutoImportCache;
updateFileWatcher(vueCompilerOptions);
return {
languagePlugins: [
createVueLanguagePlugin(
ts,
compilerOptions,
vueCompilerOptions,
s => uriConverter.asFileName(s)
),
],
setup({ project }) {
project.vue = { compilerOptions: vueCompilerOptions };
if (project.typescript) {
const directoryExists = project.typescript.languageServiceHost.directoryExists?.bind(project.typescript.languageServiceHost);
const fileExists = project.typescript.languageServiceHost.fileExists.bind(project.typescript.languageServiceHost);
const getScriptSnapshot = project.typescript.languageServiceHost.getScriptSnapshot.bind(project.typescript.languageServiceHost);
const globalTypesName = resolveGlobalTypesName(vueCompilerOptions);
const globalTypesContents = `// @ts-nocheck\nexport {};\n` + generateGlobalTypes(vueCompilerOptions);
const globalTypesSnapshot: ts.IScriptSnapshot = {
getText: (start, end) => globalTypesContents.slice(start, end),
getLength: () => globalTypesContents.length,
getChangeRange: () => undefined,
};
if (directoryExists) {
project.typescript.languageServiceHost.directoryExists = path => {
if (path.endsWith('.vue-global-types')) {
return true;
}
return directoryExists(path);
};
}
project.typescript.languageServiceHost.fileExists = path => {
if (path.endsWith(`.vue-global-types/${globalTypesName}`) || path.endsWith(`.vue-global-types\\${globalTypesName}`)) {
return true;
}
return fileExists(path);
};
project.typescript.languageServiceHost.getScriptSnapshot = path => {
if (path.endsWith(`.vue-global-types/${globalTypesName}`) || path.endsWith(`.vue-global-types\\${globalTypesName}`)) {
return globalTypesSnapshot;
}
return getScriptSnapshot(path);
};
}
},
};
}
),
getFullLanguageServicePlugins(ts, { disableAutoImportCache: params.initializationOptions.typescript.disableAutoImportCache })
);
function updateFileWatcher(vueCompilerOptions: VueCompilerOptions) {
const extensions = [
'js', 'cjs', 'mjs', 'ts', 'cts', 'mts', 'jsx', 'tsx', 'json',
...getAllExtensions(vueCompilerOptions).map(ext => ext.slice(1)),
];
const newExtensions = extensions.filter(ext => !watchingExtensions.has(ext));
if (newExtensions.length) {
for (const ext of newExtensions) {
watchingExtensions.add(ext);
}
fileWatcher?.then(dispose => dispose.dispose());
fileWatcher = server.fileWatcher.watchFiles(['**/*.{' + [...watchingExtensions].join(',') + '}']);
}
}
}