Skip to content

Commit 15b57cd

Browse files
committed
perf: hoist regexp as possible
1 parent 2013a10 commit 15b57cd

File tree

19 files changed

+84
-42
lines changed

19 files changed

+84
-42
lines changed

packages/vue-component-meta/src/index.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@ export * from './types';
1919

2020
export type ComponentMetaChecker = ReturnType<typeof baseCreate>;
2121

22+
const windowsPathReg = /\\/g;
23+
2224
export function createComponentMetaCheckerByJsonConfig(
2325
root: string,
2426
json: any,
2527
checkerOptions: MetaCheckerOptions = {},
2628
ts: typeof import('typescript/lib/tsserverlibrary') = require('typescript'),
2729
) {
28-
const rootPath = (root as path.OsPath).replace(/\\/g, '/') as path.PosixPath;
30+
const rootPath = (root as path.OsPath).replace(windowsPathReg, '/') as path.PosixPath;
2931
return createComponentMetaCheckerWorker(
3032
() => vue.createParsedCommandLineByJson(ts, ts.sys, root, json),
3133
checkerOptions,
@@ -40,7 +42,7 @@ export function createComponentMetaChecker(
4042
checkerOptions: MetaCheckerOptions = {},
4143
ts: typeof import('typescript/lib/tsserverlibrary') = require('typescript'),
4244
) {
43-
const tsconfig = (tsconfigPath as path.OsPath).replace(/\\/g, '/') as path.PosixPath;
45+
const tsconfig = (tsconfigPath as path.OsPath).replace(windowsPathReg, '/') as path.PosixPath;
4446
return createComponentMetaCheckerWorker(
4547
() => vue.createParsedCommandLine(ts, ts.sys, tsconfigPath),
4648
checkerOptions,
@@ -63,7 +65,7 @@ function createComponentMetaCheckerWorker(
6365
*/
6466

6567
let parsedCommandLine = loadParsedCommandLine();
66-
let fileNames = (parsedCommandLine.fileNames as path.OsPath[]).map<path.PosixPath>(path => path.replace(/\\/g, '/') as path.PosixPath);
68+
let fileNames = (parsedCommandLine.fileNames as path.OsPath[]).map<path.PosixPath>(path => path.replace(windowsPathReg, '/') as path.PosixPath);
6769
let projectVersion = 0;
6870

6971
const scriptSnapshots = new Map<string, ts.IScriptSnapshot>();
@@ -87,18 +89,18 @@ function createComponentMetaCheckerWorker(
8789
return {
8890
...baseCreate(_host, vue.resolveVueCompilerOptions(parsedCommandLine.vueOptions), checkerOptions, globalComponentName, ts),
8991
updateFile(fileName: string, text: string) {
90-
fileName = (fileName as path.OsPath).replace(/\\/g, '/') as path.PosixPath;
92+
fileName = (fileName as path.OsPath).replace(windowsPathReg, '/') as path.PosixPath;
9193
scriptSnapshots.set(fileName, ts.ScriptSnapshot.fromString(text));
9294
projectVersion++;
9395
},
9496
deleteFile(fileName: string) {
95-
fileName = (fileName as path.OsPath).replace(/\\/g, '/') as path.PosixPath;
97+
fileName = (fileName as path.OsPath).replace(windowsPathReg, '/') as path.PosixPath;
9698
fileNames = fileNames.filter(f => f !== fileName);
9799
projectVersion++;
98100
},
99101
reload() {
100102
parsedCommandLine = loadParsedCommandLine();
101-
fileNames = (parsedCommandLine.fileNames as path.OsPath[]).map<path.PosixPath>(path => path.replace(/\\/g, '/') as path.PosixPath);
103+
fileNames = (parsedCommandLine.fileNames as path.OsPath[]).map<path.PosixPath>(path => path.replace(windowsPathReg, '/') as path.PosixPath);
102104
this.clearCache();
103105
},
104106
clearCache() {

packages/vue-language-core/src/generators/template.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ const formatBrackets = {
4242
curly: ['0 +', '+ 0;'] as [string, string],
4343
event: ['() => ', ';'] as [string, string],
4444
};
45-
const validTsVar = /^[a-zA-Z_$][0-9a-zA-Z_$]*$/;
45+
const validTsVarReg = /^[a-zA-Z_$][0-9a-zA-Z_$]*$/;
46+
const colonReg = /:/g;
4647
// @ts-ignore
4748
const transformContext: CompilerDOM.TransformContext = {
4849
onError: () => { },
@@ -177,7 +178,7 @@ export function generate(
177178
}
178179

179180
function toCanonicalComponentName(tagText: string) {
180-
return validTsVar.test(tagText) ? tagText : capitalize(camelize(tagText.replace(/:/g, '-')));
181+
return validTsVarReg.test(tagText) ? tagText : capitalize(camelize(tagText.replace(colonReg, '-')));
181182
}
182183

183184
function getPossibleOriginalComponentName(tagText: string) {
@@ -676,7 +677,7 @@ export function generate(
676677
else {
677678
codes.push(`let ${var_originalComponent}!: `);
678679
for (const componentName of getPossibleOriginalComponentName(tag)) {
679-
codes.push(`'${componentName}' extends keyof typeof __VLS_ctx ? typeof __VLS_ctx${validTsVar.test(componentName) ? `.${componentName}` : `['${componentName}']`} : `);
680+
codes.push(`'${componentName}' extends keyof typeof __VLS_ctx ? typeof __VLS_ctx${validTsVarReg.test(componentName) ? `.${componentName}` : `['${componentName}']`} : `);
680681
}
681682
codes.push(`typeof __VLS_resolvedLocalAndGlobalComponents['${toCanonicalComponentName(tag)}'];\n`);
682683
}
@@ -1776,7 +1777,7 @@ export function generate(
17761777

17771778
function createObjectPropertyCode(a: Code, astHolder?: any): Code[] {
17781779
const aStr = typeof a === 'string' ? a : a[0];
1779-
if (validTsVar.test(aStr)) {
1780+
if (validTsVarReg.test(aStr)) {
17801781
return [a];
17811782
}
17821783
else if (aStr.startsWith('[') && aStr.endsWith(']') && astHolder) {
@@ -1861,7 +1862,7 @@ export function generate(
18611862

18621863
function createPropertyAccessCode(a: Code, astHolder?: any): Code[] {
18631864
const aStr = typeof a === 'string' ? a : a[0];
1864-
if (!compilerOptions.noPropertyAccessFromIndexSignature && validTsVar.test(aStr)) {
1865+
if (!compilerOptions.noPropertyAccessFromIndexSignature && validTsVarReg.test(aStr)) {
18651866
return ['.', a];
18661867
}
18671868
else if (aStr.startsWith('[') && aStr.endsWith(']')) {

packages/vue-language-core/src/plugins/file-html.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import type { SFCParseResult } from '@vue/compiler-sfc';
22
import { VueLanguagePlugin } from '../types';
33

4+
const sfcBlockReg = /\<(script|style)\b([\s\S]*?)\>([\s\S]*?)\<\/\1\>/g;
5+
const langReg = /\blang\s*=\s*(['\"]?)(\S*)\b\1/;
6+
47
const plugin: VueLanguagePlugin = () => {
58

69
return {
@@ -29,9 +32,6 @@ const plugin: VueLanguagePlugin = () => {
2932

3033
let templateContent = content;
3134

32-
const sfcBlockReg = /\<(script|style)\b([\s\S]*?)\>([\s\S]*?)\<\/\1\>/g;
33-
const langReg = /\blang\s*=\s*(['\"]?)(\S*)\b\1/;
34-
3535
for (const match of content.matchAll(sfcBlockReg)) {
3636

3737
const matchText = match[0];

packages/vue-language-core/src/plugins/file-md.ts

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,13 @@ import type { SFCBlock } from '@vue/compiler-sfc';
33
import { VueLanguagePlugin } from '../types';
44
import { parse } from '../utils/parseSfc';
55

6+
const codeblockReg = /```[\s\S]+?```/g;
7+
const inlineCodeblockReg = /`[^\n`]+?`/g;
8+
const scriptSetupReg = /\\\<[\s\S]+?\>\n?/g;
9+
const sfcBlockReg = /\<(script|style)\b[\s\S]*?\>([\s\S]*?)\<\/\1\>/g;
10+
const angleBracketReg = /\<\S*\:\S*\>/g;
11+
const linkReg = /\[[\s\S]*?\]\([\s\S]*?\)/g;
12+
613
const plugin: VueLanguagePlugin = () => {
714

815
return {
@@ -15,13 +22,12 @@ const plugin: VueLanguagePlugin = () => {
1522

1623
content = content
1724
// code block
18-
.replace(/```[\s\S]+?```/g, match => '```' + ' '.repeat(match.length - 6) + '```')
25+
.replace(codeblockReg, match => '```' + ' '.repeat(match.length - 6) + '```')
1926
// inline code block
20-
.replace(/`[^\n`]+?`/g, match => `\`${' '.repeat(match.length - 2)}\``)
27+
.replace(inlineCodeblockReg, match => `\`${' '.repeat(match.length - 2)}\``)
2128
// # \<script setup>
22-
.replace(/\\\<[\s\S]+?\>\n?/g, match => ' '.repeat(match.length));
29+
.replace(scriptSetupReg, match => ' '.repeat(match.length));
2330

24-
const sfcBlockReg = /\<(script|style)\b[\s\S]*?\>([\s\S]*?)\<\/\1\>/g;
2531
const codes: Segment[] = [];
2632

2733
for (const match of content.matchAll(sfcBlockReg)) {
@@ -35,9 +41,9 @@ const plugin: VueLanguagePlugin = () => {
3541

3642
content = content
3743
// angle bracket: <http://foo.com>
38-
.replace(/\<\S*\:\S*\>/g, match => ' '.repeat(match.length))
44+
.replace(angleBracketReg, match => ' '.repeat(match.length))
3945
// [foo](http://foo.com)
40-
.replace(/\[[\s\S]*?\]\([\s\S]*?\)/g, match => ' '.repeat(match.length));
46+
.replace(linkReg, match => ' '.repeat(match.length));
4147

4248
codes.push('<template>\n');
4349
codes.push([content, undefined, 0]);

packages/vue-language-core/src/plugins/vue-sfc-customblocks.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { FileCapabilities, FileRangeCapabilities } from '@volar/language-core';
22
import { VueLanguagePlugin } from '../types';
33

4+
const customBlockReg = /^(.*)\.customBlock_([^_]+)_(\d+)\.([^.]+)$/;
5+
46
const plugin: VueLanguagePlugin = () => {
57

68
return {
@@ -17,7 +19,7 @@ const plugin: VueLanguagePlugin = () => {
1719
},
1820

1921
resolveEmbeddedFile(_fileName, sfc, embeddedFile) {
20-
const match = embeddedFile.fileName.match(/^(.*)\.customBlock_([^_]+)_(\d+)\.([^.]+)$/);
22+
const match = embeddedFile.fileName.match(customBlockReg);
2123
if (match) {
2224
const index = parseInt(match[3]);
2325
const customBlock = sfc.customBlocks[index];

packages/vue-language-core/src/plugins/vue-sfc-scripts.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import { FileCapabilities, FileKind } from '@volar/language-core';
22
import { VueLanguagePlugin } from '../types';
33

4+
const scriptFormatReg = /^(.*)\.script_format\.([^.]+)$/;
5+
const scriptSetupFormatReg = /^(.*)\.scriptSetup_format\.([^.]+)$/;
6+
47
const plugin: VueLanguagePlugin = () => {
58

69
return {
@@ -19,8 +22,8 @@ const plugin: VueLanguagePlugin = () => {
1922
},
2023

2124
resolveEmbeddedFile(_fileName, sfc, embeddedFile) {
22-
const scriptMatch = embeddedFile.fileName.match(/^(.*)\.script_format\.([^.]+)$/);
23-
const scriptSetupMatch = embeddedFile.fileName.match(/^(.*)\.scriptSetup_format\.([^.]+)$/);
25+
const scriptMatch = embeddedFile.fileName.match(scriptFormatReg);
26+
const scriptSetupMatch = embeddedFile.fileName.match(scriptSetupFormatReg);
2427
const script = scriptMatch ? sfc.script : scriptSetupMatch ? sfc.scriptSetup : undefined;
2528
if (script) {
2629
embeddedFile.kind = FileKind.TextFile;

packages/vue-language-core/src/plugins/vue-sfc-styles.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { FileCapabilities, FileRangeCapabilities } from '@volar/language-core';
22
import { VueLanguagePlugin } from '../types';
33

4+
const styleReg = /^(.*)\.style_(\d+)\.([^.]+)$/;
5+
46
const plugin: VueLanguagePlugin = () => {
57

68
return {
@@ -17,7 +19,7 @@ const plugin: VueLanguagePlugin = () => {
1719
},
1820

1921
resolveEmbeddedFile(_fileName, sfc, embeddedFile) {
20-
const match = embeddedFile.fileName.match(/^(.*)\.style_(\d+)\.([^.]+)$/);
22+
const match = embeddedFile.fileName.match(styleReg);
2123
if (match) {
2224
const index = parseInt(match[2]);
2325
const style = sfc.styles[index];

packages/vue-language-core/src/plugins/vue-sfc-template.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { FileCapabilities, FileRangeCapabilities } from '@volar/language-core';
22
import { VueLanguagePlugin } from '../types';
33

4+
const templateReg = /^(.*)\.template\.([^.]+)$/;
5+
46
const plugin: VueLanguagePlugin = () => {
57

68
return {
@@ -15,7 +17,7 @@ const plugin: VueLanguagePlugin = () => {
1517
},
1618

1719
resolveEmbeddedFile(_fileName, sfc, embeddedFile) {
18-
const match = embeddedFile.fileName.match(/^(.*)\.template\.([^.]+)$/);
20+
const match = embeddedFile.fileName.match(templateReg);
1921
if (match && sfc.template) {
2022
embeddedFile.capabilities = FileCapabilities.full;
2123
embeddedFile.content.push([

packages/vue-language-core/src/plugins/vue-tsx.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ import { Sfc, VueLanguagePlugin } from '../types';
77
import { FileCapabilities, FileKind } from '@volar/language-core';
88
import * as muggle from 'muggle-string';
99

10+
const templateFormatReg = /^\.template_format\.ts$/;
11+
const templateStyleCssReg = /^\.template_style\.css$/;
12+
1013
const plugin: VueLanguagePlugin = ({ modules, vueCompilerOptions, compilerOptions, codegenStack }) => {
1114

1215
const ts = modules.typescript;
@@ -54,7 +57,7 @@ const plugin: VueLanguagePlugin = ({ modules, vueCompilerOptions, compilerOption
5457
embeddedFile.mirrorBehaviorMappings = [...tsx.mirrorBehaviorMappings];
5558
}
5659
}
57-
else if (suffix.match(/^\.template_format\.ts$/)) {
60+
else if (suffix.match(templateFormatReg)) {
5861

5962
embeddedFile.parentFileName = fileName + '.template.' + sfc.template?.lang;
6063
embeddedFile.kind = FileKind.TextFile;
@@ -86,7 +89,7 @@ const plugin: VueLanguagePlugin = ({ modules, vueCompilerOptions, compilerOption
8689
}
8790
}
8891
}
89-
else if (suffix.match(/^\.template_style\.css$/)) {
92+
else if (suffix.match(templateStyleCssReg)) {
9093

9194
embeddedFile.parentFileName = fileName + '.template.' + sfc.template?.lang;
9295

packages/vue-language-core/src/sourceFile.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import { parseCssVars } from './utils/parseCssVars';
1010
import { parseCssClassNames } from './utils/parseCssClassNames';
1111
import { VueCompilerOptions } from './types';
1212

13+
const jsxReg = /^\.(js|ts)x?$/;
14+
1315
export class VueEmbeddedFile {
1416

1517
public parentFileName?: string;
@@ -52,7 +54,7 @@ export class VueFile implements VirtualFile {
5254
}
5355

5456
get mainScriptName() {
55-
return this._allEmbeddedFiles.value.find(e => e.file.fileName.replace(this.fileName, '').match(/^\.(js|ts)x?$/))?.file.fileName ?? '';
57+
return this._allEmbeddedFiles.value.find(e => e.file.fileName.replace(this.fileName, '').match(jsxReg))?.file.fileName ?? '';
5658
}
5759

5860
get embeddedFiles() {

packages/vue-language-core/src/utils/parseCssClassNames.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import { clearComments } from './parseCssVars';
22

3+
const cssClassNameReg = /(?=([\.]{1}[a-zA-Z_]+[\w\_\-]*)[\s\.\+\{\>#\:]{1})/g;
4+
35
export function* parseCssClassNames(styleContent: string) {
46
styleContent = clearComments(styleContent);
5-
const cssClassNameRegex = /(?=([\.]{1}[a-zA-Z_]+[\w\_\-]*)[\s\.\+\{\>#\:]{1})/g;
6-
const matchs = styleContent.matchAll(cssClassNameRegex);
7+
const matchs = styleContent.matchAll(cssClassNameReg);
78
for (const match of matchs) {
89
if (match.index !== undefined) {
910
const matchText = match[1];

packages/vue-language-core/src/utils/parseCssVars.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
// https://github.com/vuejs/core/blob/main/packages/compiler-sfc/src/cssVars.ts#L47-L61
2+
3+
const vBindCssVarReg = /\bv-bind\(\s*(?:'([^']+)'|"([^"]+)"|([^'"][^)]*))\s*\)/g;
4+
const commentReg1 = /\/\*([\s\S]*?)\*\//g;
5+
const commentReg2 = /\/\/([\s\S]*?)\n/g;
6+
27
export function* parseCssVars(styleContent: string) {
38
styleContent = clearComments(styleContent);
4-
const reg = /\bv-bind\(\s*(?:'([^']+)'|"([^"]+)"|([^'"][^)]*))\s*\)/g;
5-
const matchs = styleContent.matchAll(reg);
9+
const matchs = styleContent.matchAll(vBindCssVarReg);
610
for (const match of matchs) {
711
if (match.index !== undefined) {
812
const matchText = match[1] ?? match[2] ?? match[3];
@@ -16,6 +20,6 @@ export function* parseCssVars(styleContent: string) {
1620

1721
export function clearComments(css: string) {
1822
return css
19-
.replace(/\/\*([\s\S]*?)\*\//g, match => `/*${' '.repeat(match.length - 4)}*/`)
20-
.replace(/\/\/([\s\S]*?)\n/g, match => `//${' '.repeat(match.length - 3)}\n`);
23+
.replace(commentReg1, match => `/*${' '.repeat(match.length - 4)}*/`)
24+
.replace(commentReg2, match => `//${' '.repeat(match.length - 3)}\n`);
2125
}

packages/vue-language-service/src/languageService.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ export function resolveConfig(
4747
return config;
4848
}
4949

50+
const unicodeReg = /\\u/g;
51+
5052
function resolvePlugins(
5153
services: Config['services'],
5254
vueCompilerOptions: VueCompilerOptions,
@@ -193,7 +195,7 @@ function resolvePlugins(
193195
transformed = true;
194196
item.additionalTextEdits.push({
195197
range: editRange,
196-
newText: unescape(printText.replace(/\\u/g, '%u')),
198+
newText: unescape(printText.replace(unicodeReg, '%u')),
197199
});
198200
}
199201
else if (exportDefault.args && exportDefault.argsNode) {
@@ -212,7 +214,7 @@ function resolvePlugins(
212214
transformed = true;
213215
item.additionalTextEdits.push({
214216
range: editRange,
215-
newText: unescape(printText.replace(/\\u/g, '%u')),
217+
newText: unescape(printText.replace(unicodeReg, '%u')),
216218
});
217219
}
218220
}

packages/vue-language-service/src/plugins/vue-autoinsert-dotvalue.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ function isTsDocument(document: TextDocument) {
8686
document.languageId === 'typescriptreact';
8787
}
8888

89+
const charReg = /\w/;
90+
8991
export function isCharacterTyping(document: TextDocument, options: AutoInsertionContext) {
9092

9193
const lastCharacter = options.lastChange.text[options.lastChange.text.length - 1];
@@ -106,7 +108,7 @@ export function isCharacterTyping(document: TextDocument, options: AutoInsertion
106108
return false;
107109
}
108110

109-
return /\w/.test(lastCharacter) && !/\w/.test(nextCharacter);
111+
return charReg.test(lastCharacter) && !charReg.test(nextCharacter);
110112
}
111113

112114
export function isBlacklistNode(ts: typeof import('typescript/lib/tsserverlibrary'), node: ts.Node, pos: number, allowAccessDotValue: boolean) {

packages/vue-language-service/src/plugins/vue-directive-comments.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ const cmds = [
66
'vue-expect-error',
77
];
88

9+
const directiveCommentReg = /<!--\s+@/;
10+
911
const plugin: Service = (): ReturnType<Service> => {
1012

1113
return {
@@ -18,7 +20,7 @@ const plugin: Service = (): ReturnType<Service> => {
1820
return;
1921

2022
const line = document.getText({ start: { line: position.line, character: 0 }, end: position });
21-
const cmdStart = line.match(/<!--\s+@/);
23+
const cmdStart = line.match(directiveCommentReg);
2224
if (!cmdStart)
2325
return;
2426

0 commit comments

Comments
 (0)