Skip to content

Commit 98b24e8

Browse files
committed
perf: cache canonical root file names with string Set
1 parent 9b13a26 commit 98b24e8

File tree

8 files changed

+56
-99
lines changed

8 files changed

+56
-99
lines changed

packages/component-meta/lib/base.ts

+3-14
Original file line numberDiff line numberDiff line change
@@ -160,20 +160,9 @@ export function baseCreate(
160160
const vueLanguagePlugin = vue.createVueLanguagePlugin(
161161
ts,
162162
id => id,
163-
fileName => {
164-
if (ts.sys.useCaseSensitiveFileNames) {
165-
return host.getScriptFileNames().includes(fileName) ?? false;
166-
}
167-
else {
168-
const lowerFileName = fileName.toLowerCase();
169-
for (const rootFile of host.getScriptFileNames()) {
170-
if (rootFile.toLowerCase() === lowerFileName) {
171-
return true;
172-
}
173-
}
174-
return false;
175-
}
176-
},
163+
ts.sys.useCaseSensitiveFileNames,
164+
() => host.getProjectVersion?.() ?? '',
165+
() => host.getScriptFileNames(),
177166
host.getCompilationSettings(),
178167
vueCompilerOptions,
179168
);

packages/language-core/lib/languageModule.ts

+23-3
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,21 @@ function getFileRegistryKey(
4848
return JSON.stringify(values);
4949
}
5050

51+
interface _Plugin extends LanguagePlugin<VueGeneratedCode> {
52+
getCanonicalFileName: (fileName: string) => string;
53+
pluginContext: Parameters<VueLanguagePlugin>[0];
54+
}
55+
5156
export function createVueLanguagePlugin(
5257
ts: typeof import('typescript'),
5358
getFileName: (fileId: string) => string,
54-
isValidGlobalTypesHolder: (fileName: string) => boolean,
59+
useCaseSensitiveFileNames: boolean,
60+
getProjectVersion: () => string,
61+
getScriptFileNames: () => string[] | Set<string>,
5562
compilerOptions: ts.CompilerOptions,
5663
vueCompilerOptions: VueCompilerOptions,
5764
codegenStack: boolean = false,
58-
): LanguagePlugin<VueGeneratedCode> {
65+
): _Plugin {
5966
const allowLanguageIds = new Set(['vue']);
6067
const pluginContext: Parameters<VueLanguagePlugin>[0] = {
6168
modules: {
@@ -81,11 +88,24 @@ export function createVueLanguagePlugin(
8188
allowLanguageIds.add('html');
8289
}
8390

91+
const getCanonicalFileName = useCaseSensitiveFileNames
92+
? (fileName: string) => fileName
93+
: (fileName: string) => fileName.toLowerCase();
94+
let canonicalRootFileNames = new Set<string>();
95+
let canonicalRootFileNamesVersion: string | undefined;
96+
8497
return {
98+
getCanonicalFileName,
99+
pluginContext,
85100
createVirtualCode(fileId, languageId, snapshot) {
86101
if (allowLanguageIds.has(languageId)) {
87102
const fileName = getFileName(fileId);
88-
if (!pluginContext.globalTypesHolder && isValidGlobalTypesHolder(fileName)) {
103+
const projectVersion = getProjectVersion();
104+
if (projectVersion !== canonicalRootFileNamesVersion) {
105+
canonicalRootFileNames = new Set([...getScriptFileNames()].map(getCanonicalFileName));
106+
canonicalRootFileNamesVersion = projectVersion;
107+
}
108+
if (!pluginContext.globalTypesHolder && canonicalRootFileNames.has(getCanonicalFileName(fileName))) {
89109
pluginContext.globalTypesHolder = fileName;
90110
}
91111
const fileRegistry = getFileRegistry(pluginContext.globalTypesHolder === fileName);

packages/language-server/node.ts

+3-14
Original file line numberDiff line numberDiff line change
@@ -80,20 +80,9 @@ connection.onInitialize(async params => {
8080
const vueLanguagePlugin = createVueLanguagePlugin(
8181
tsdk.typescript,
8282
serviceEnv.typescript!.uriToFileName,
83-
fileName => {
84-
if (projectContext.typescript?.sys.useCaseSensitiveFileNames ?? false) {
85-
return projectContext.typescript?.host.getScriptFileNames().includes(fileName) ?? false;
86-
}
87-
else {
88-
const lowerFileName = fileName.toLowerCase();
89-
for (const rootFile of projectContext.typescript?.host.getScriptFileNames() ?? []) {
90-
if (rootFile.toLowerCase() === lowerFileName) {
91-
return true;
92-
}
93-
}
94-
return false;
95-
}
96-
},
83+
projectContext.typescript?.sys.useCaseSensitiveFileNames ?? false,
84+
() => projectContext.typescript?.host.getProjectVersion?.() ?? '',
85+
() => projectContext.typescript?.host.getScriptFileNames() ?? [],
9786
commandLine?.options ?? {},
9887
vueOptions,
9988
options.codegenStack,

packages/language-service/tests/utils/createTester.ts

+3-14
Original file line numberDiff line numberDiff line change
@@ -32,20 +32,9 @@ function createTester(rootUri: string) {
3232
const vueLanguagePlugin = createVueLanguagePlugin(
3333
ts,
3434
serviceEnv.typescript!.uriToFileName,
35-
fileName => {
36-
if (ts.sys.useCaseSensitiveFileNames) {
37-
return projectHost.getScriptFileNames().includes(fileName);
38-
}
39-
else {
40-
const lowerFileName = fileName.toLowerCase();
41-
for (const rootFile of projectHost.getScriptFileNames()) {
42-
if (rootFile.toLowerCase() === lowerFileName) {
43-
return true;
44-
}
45-
}
46-
return false;
47-
}
48-
},
35+
ts.sys.useCaseSensitiveFileNames,
36+
() => projectHost.getProjectVersion?.() ?? '',
37+
() => projectHost.getScriptFileNames(),
4938
parsedCommandLine.options,
5039
parsedCommandLine.vueOptions,
5140
);

packages/language-service/tests/utils/format.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ const resolvedVueOptions = resolveVueCompilerOptions({});
77
const vueLanguagePlugin = createVueLanguagePlugin(
88
ts,
99
fileId => formatter.env.typescript!.uriToFileName(fileId),
10-
() => false,
10+
false,
11+
() => '',
12+
() => [],
1113
{},
1214
resolvedVueOptions,
1315
);

packages/tsc/index.ts

+15-24
Original file line numberDiff line numberDiff line change
@@ -16,37 +16,28 @@ export function run() {
1616
const vueOptions = typeof configFilePath === 'string'
1717
? vue.createParsedCommandLine(ts, ts.sys, configFilePath.replace(windowsPathReg, '/')).vueOptions
1818
: vue.resolveVueCompilerOptions({});
19-
const writeFile = options.host!.writeFile.bind(options.host);
20-
const getCanonicalFileName = options.host?.useCaseSensitiveFileNames?.()
21-
? (fileName: string) => fileName
22-
: (fileName: string) => fileName.toLowerCase();
23-
const canonicalRootFileNames = new Set(
24-
options.rootNames
25-
.map(rootName => rootName.replace(windowsPathReg, '/'))
26-
.map(getCanonicalFileName)
27-
);
28-
const canonicalGlobalTypesHolderFileNames = new Set<string>();
29-
options.host!.writeFile = (fileName, contents, ...args) => {
30-
if (
31-
fileName.endsWith('.d.ts')
32-
&& canonicalGlobalTypesHolderFileNames.has(getCanonicalFileName(fileName.replace(windowsPathReg, '/')).slice(0, -5))
33-
) {
34-
contents = removeEmitGlobalTypes(contents);
35-
}
36-
return writeFile(fileName, contents, ...args);
37-
};
3819
if (
3920
runExtensions.length === vueOptions.extensions.length
4021
&& runExtensions.every(ext => vueOptions.extensions.includes(ext))
4122
) {
23+
const writeFile = options.host!.writeFile.bind(options.host);
24+
options.host!.writeFile = (fileName, contents, ...args) => {
25+
if (
26+
fileName.endsWith('.d.ts')
27+
&& vueLanguagePlugin
28+
.getCanonicalFileName(fileName.replace(windowsPathReg, '/'))
29+
.slice(0, -5) === vueLanguagePlugin.pluginContext.globalTypesHolder
30+
) {
31+
contents = removeEmitGlobalTypes(contents);
32+
}
33+
return writeFile(fileName, contents, ...args);
34+
};
4235
const vueLanguagePlugin = vue.createVueLanguagePlugin(
4336
ts,
4437
id => id,
45-
fileName => {
46-
const canonicalFileName = getCanonicalFileName(fileName);
47-
canonicalGlobalTypesHolderFileNames.add(canonicalFileName);
48-
return canonicalRootFileNames.has(canonicalFileName);
49-
},
38+
options.host?.useCaseSensitiveFileNames?.() ?? false,
39+
() => '',
40+
() => options.rootNames.map(rootName => rootName.replace(windowsPathReg, '/')),
5041
options.options,
5142
vueOptions,
5243
false,

packages/tsc/tests/dts.spec.ts

+3-15
Original file line numberDiff line numberDiff line change
@@ -35,21 +35,9 @@ describe('vue-tsc-dts', () => {
3535
const vueLanguagePlugin = vue.createVueLanguagePlugin(
3636
ts,
3737
id => id,
38-
fileName => {
39-
const rootFileNames = options.rootNames.map(rootName => rootName.replace(windowsPathReg, '/'));
40-
if (options.host?.useCaseSensitiveFileNames?.()) {
41-
return rootFileNames.includes(fileName);
42-
}
43-
else {
44-
const lowerFileName = fileName.toLowerCase();
45-
for (const rootFileName of rootFileNames) {
46-
if (rootFileName.toLowerCase() === lowerFileName) {
47-
return true;
48-
}
49-
}
50-
return false;
51-
}
52-
},
38+
options.host?.useCaseSensitiveFileNames?.() ?? false,
39+
() => '',
40+
() => options.rootNames.map(rootName => rootName.replace(windowsPathReg, '/')),
5341
options.options,
5442
vueOptions,
5543
false,

packages/typescript-plugin/index.ts

+3-14
Original file line numberDiff line numberDiff line change
@@ -30,20 +30,9 @@ function createLanguageServicePlugin(): ts.server.PluginModuleFactory {
3030
const languagePlugin = vue.createVueLanguagePlugin(
3131
ts,
3232
id => id,
33-
fileName => {
34-
if (info.languageServiceHost.useCaseSensitiveFileNames?.() ?? false) {
35-
return externalFiles.get(info.project)?.has(fileName) ?? false;
36-
}
37-
else {
38-
const lowerFileName = fileName.toLowerCase();
39-
for (const externalFile of externalFiles.get(info.project) ?? []) {
40-
if (externalFile.toLowerCase() === lowerFileName) {
41-
return true;
42-
}
43-
}
44-
return false;
45-
}
46-
},
33+
info.languageServiceHost.useCaseSensitiveFileNames?.() ?? false,
34+
() => info.languageServiceHost.getProjectVersion?.() ?? '',
35+
() => externalFiles.get(info.project) ?? [],
4736
info.languageServiceHost.getCompilationSettings(),
4837
vueOptions,
4938
);

0 commit comments

Comments
 (0)