-
-
Notifications
You must be signed in to change notification settings - Fork 34
/
Copy pathget-language-service.js
100 lines (79 loc) · 2.66 KB
/
get-language-service.js
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
const ts = require('typescript');
const { findTsconfig } = require('./find-tsconfig');
const { getTypeScriptLanguageServiceHost } = require('./service-host');
/**
* Get the correct language service for the given parser.
*
* @param {import('prettier').ParserOptions['parser']} parser
* @param {string} filepath
* @param {string} code
*
* @returns {import('typescript').LanguageService}
*/
const getLanguageService = (parser, filepath, code) => {
const langaugeServiceHost = getTypeScriptLanguageServiceHost(filepath, code);
const languageService = ts.createLanguageService(langaugeServiceHost);
switch (parser) {
case 'vue':
return getVueDecoratedProxyLanguageService(langaugeServiceHost, languageService, filepath);
/** @todo add svelte support */
default:
return languageService;
}
};
/**
* Decorate a language service so it can handle Vue files.
*
* @param {import('typescript').LanguageServiceHost} langaugeServiceHost
* @param {import('typescript').LanguageService} languageService
* @param {string} filepath
*
* @returns {import('typescript').LanguageService}
*/
function getVueDecoratedProxyLanguageService(langaugeServiceHost, languageService, filepath) {
const vueTscDir = tryCatch(() => require('path').dirname(require.resolve('vue-tsc/package.json')));
if (!vueTscDir) {
console.error('Please install vue-tsc to organize imports in Vue files.');
return languageService;
}
const { createProxyLanguageService, decorateLanguageServiceHost } = require(
require.resolve('@volar/typescript', { paths: [vueTscDir] }),
);
/** @type {import('@vue/language-core')} */
const {
createLanguage,
createVueLanguagePlugin,
FileMap,
createParsedCommandLine,
resolveVueCompilerOptions,
} = require(require.resolve('@vue/language-core', { paths: [vueTscDir] }));
const tsconfig = findTsconfig(filepath);
const vueLanguagePlugin = createVueLanguagePlugin(
ts,
langaugeServiceHost.getCompilationSettings(),
tsconfig ? createParsedCommandLine(ts, ts.sys, tsconfig).vueOptions : resolveVueCompilerOptions({}),
(s) => s,
);
const language = createLanguage([vueLanguagePlugin], new FileMap(ts.sys.useCaseSensitiveFileNames), () => {});
const snapshot = langaugeServiceHost.getScriptSnapshot(filepath);
if (snapshot) {
language.scripts.set(filepath, snapshot);
}
const { initialize, proxy } = createProxyLanguageService(languageService);
initialize(language);
decorateLanguageServiceHost(ts, language, langaugeServiceHost);
return proxy;
}
/**
* @template T
* @param {() => T} fn
* @returns {T | undefined}
*/
function tryCatch(fn) {
try {
return fn();
} catch {
return undefined;
}
}
module.exports = { getLanguageService };