Skip to content

Commit

Permalink
perf: hoist regexp as possible
Browse files Browse the repository at this point in the history
  • Loading branch information
so1ve committed Jul 7, 2023
1 parent 2013a10 commit 15b57cd
Show file tree
Hide file tree
Showing 19 changed files with 84 additions and 42 deletions.
14 changes: 8 additions & 6 deletions packages/vue-component-meta/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,15 @@ export * from './types';

export type ComponentMetaChecker = ReturnType<typeof baseCreate>;

const windowsPathReg = /\\/g;

export function createComponentMetaCheckerByJsonConfig(
root: string,
json: any,
checkerOptions: MetaCheckerOptions = {},
ts: typeof import('typescript/lib/tsserverlibrary') = require('typescript'),
) {
const rootPath = (root as path.OsPath).replace(/\\/g, '/') as path.PosixPath;
const rootPath = (root as path.OsPath).replace(windowsPathReg, '/') as path.PosixPath;
return createComponentMetaCheckerWorker(
() => vue.createParsedCommandLineByJson(ts, ts.sys, root, json),
checkerOptions,
Expand All @@ -40,7 +42,7 @@ export function createComponentMetaChecker(
checkerOptions: MetaCheckerOptions = {},
ts: typeof import('typescript/lib/tsserverlibrary') = require('typescript'),
) {
const tsconfig = (tsconfigPath as path.OsPath).replace(/\\/g, '/') as path.PosixPath;
const tsconfig = (tsconfigPath as path.OsPath).replace(windowsPathReg, '/') as path.PosixPath;
return createComponentMetaCheckerWorker(
() => vue.createParsedCommandLine(ts, ts.sys, tsconfigPath),
checkerOptions,
Expand All @@ -63,7 +65,7 @@ function createComponentMetaCheckerWorker(
*/

let parsedCommandLine = loadParsedCommandLine();
let fileNames = (parsedCommandLine.fileNames as path.OsPath[]).map<path.PosixPath>(path => path.replace(/\\/g, '/') as path.PosixPath);
let fileNames = (parsedCommandLine.fileNames as path.OsPath[]).map<path.PosixPath>(path => path.replace(windowsPathReg, '/') as path.PosixPath);
let projectVersion = 0;

const scriptSnapshots = new Map<string, ts.IScriptSnapshot>();
Expand All @@ -87,18 +89,18 @@ function createComponentMetaCheckerWorker(
return {
...baseCreate(_host, vue.resolveVueCompilerOptions(parsedCommandLine.vueOptions), checkerOptions, globalComponentName, ts),
updateFile(fileName: string, text: string) {
fileName = (fileName as path.OsPath).replace(/\\/g, '/') as path.PosixPath;
fileName = (fileName as path.OsPath).replace(windowsPathReg, '/') as path.PosixPath;
scriptSnapshots.set(fileName, ts.ScriptSnapshot.fromString(text));
projectVersion++;
},
deleteFile(fileName: string) {
fileName = (fileName as path.OsPath).replace(/\\/g, '/') as path.PosixPath;
fileName = (fileName as path.OsPath).replace(windowsPathReg, '/') as path.PosixPath;
fileNames = fileNames.filter(f => f !== fileName);
projectVersion++;
},
reload() {
parsedCommandLine = loadParsedCommandLine();
fileNames = (parsedCommandLine.fileNames as path.OsPath[]).map<path.PosixPath>(path => path.replace(/\\/g, '/') as path.PosixPath);
fileNames = (parsedCommandLine.fileNames as path.OsPath[]).map<path.PosixPath>(path => path.replace(windowsPathReg, '/') as path.PosixPath);
this.clearCache();
},
clearCache() {
Expand Down
11 changes: 6 additions & 5 deletions packages/vue-language-core/src/generators/template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ const formatBrackets = {
curly: ['0 +', '+ 0;'] as [string, string],
event: ['() => ', ';'] as [string, string],
};
const validTsVar = /^[a-zA-Z_$][0-9a-zA-Z_$]*$/;
const validTsVarReg = /^[a-zA-Z_$][0-9a-zA-Z_$]*$/;
const colonReg = /:/g;
// @ts-ignore
const transformContext: CompilerDOM.TransformContext = {
onError: () => { },
Expand Down Expand Up @@ -177,7 +178,7 @@ export function generate(
}

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

function getPossibleOriginalComponentName(tagText: string) {
Expand Down Expand Up @@ -676,7 +677,7 @@ export function generate(
else {
codes.push(`let ${var_originalComponent}!: `);
for (const componentName of getPossibleOriginalComponentName(tag)) {
codes.push(`'${componentName}' extends keyof typeof __VLS_ctx ? typeof __VLS_ctx${validTsVar.test(componentName) ? `.${componentName}` : `['${componentName}']`} : `);
codes.push(`'${componentName}' extends keyof typeof __VLS_ctx ? typeof __VLS_ctx${validTsVarReg.test(componentName) ? `.${componentName}` : `['${componentName}']`} : `);
}
codes.push(`typeof __VLS_resolvedLocalAndGlobalComponents['${toCanonicalComponentName(tag)}'];\n`);
}
Expand Down Expand Up @@ -1776,7 +1777,7 @@ export function generate(

function createObjectPropertyCode(a: Code, astHolder?: any): Code[] {
const aStr = typeof a === 'string' ? a : a[0];
if (validTsVar.test(aStr)) {
if (validTsVarReg.test(aStr)) {
return [a];
}
else if (aStr.startsWith('[') && aStr.endsWith(']') && astHolder) {
Expand Down Expand Up @@ -1861,7 +1862,7 @@ export function generate(

function createPropertyAccessCode(a: Code, astHolder?: any): Code[] {
const aStr = typeof a === 'string' ? a : a[0];
if (!compilerOptions.noPropertyAccessFromIndexSignature && validTsVar.test(aStr)) {
if (!compilerOptions.noPropertyAccessFromIndexSignature && validTsVarReg.test(aStr)) {
return ['.', a];
}
else if (aStr.startsWith('[') && aStr.endsWith(']')) {
Expand Down
6 changes: 3 additions & 3 deletions packages/vue-language-core/src/plugins/file-html.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import type { SFCParseResult } from '@vue/compiler-sfc';
import { VueLanguagePlugin } from '../types';

const sfcBlockReg = /\<(script|style)\b([\s\S]*?)\>([\s\S]*?)\<\/\1\>/g;
const langReg = /\blang\s*=\s*(['\"]?)(\S*)\b\1/;

const plugin: VueLanguagePlugin = () => {

return {
Expand Down Expand Up @@ -29,9 +32,6 @@ const plugin: VueLanguagePlugin = () => {

let templateContent = content;

const sfcBlockReg = /\<(script|style)\b([\s\S]*?)\>([\s\S]*?)\<\/\1\>/g;
const langReg = /\blang\s*=\s*(['\"]?)(\S*)\b\1/;

for (const match of content.matchAll(sfcBlockReg)) {

const matchText = match[0];
Expand Down
18 changes: 12 additions & 6 deletions packages/vue-language-core/src/plugins/file-md.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@ import type { SFCBlock } from '@vue/compiler-sfc';
import { VueLanguagePlugin } from '../types';
import { parse } from '../utils/parseSfc';

const codeblockReg = /```[\s\S]+?```/g;
const inlineCodeblockReg = /`[^\n`]+?`/g;
const scriptSetupReg = /\\\<[\s\S]+?\>\n?/g;
const sfcBlockReg = /\<(script|style)\b[\s\S]*?\>([\s\S]*?)\<\/\1\>/g;
const angleBracketReg = /\<\S*\:\S*\>/g;
const linkReg = /\[[\s\S]*?\]\([\s\S]*?\)/g;

const plugin: VueLanguagePlugin = () => {

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

content = content
// code block
.replace(/```[\s\S]+?```/g, match => '```' + ' '.repeat(match.length - 6) + '```')
.replace(codeblockReg, match => '```' + ' '.repeat(match.length - 6) + '```')
// inline code block
.replace(/`[^\n`]+?`/g, match => `\`${' '.repeat(match.length - 2)}\``)
.replace(inlineCodeblockReg, match => `\`${' '.repeat(match.length - 2)}\``)
// # \<script setup>
.replace(/\\\<[\s\S]+?\>\n?/g, match => ' '.repeat(match.length));
.replace(scriptSetupReg, match => ' '.repeat(match.length));

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

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

content = content
// angle bracket: <http://foo.com>
.replace(/\<\S*\:\S*\>/g, match => ' '.repeat(match.length))
.replace(angleBracketReg, match => ' '.repeat(match.length))
// [foo](http://foo.com)
.replace(/\[[\s\S]*?\]\([\s\S]*?\)/g, match => ' '.repeat(match.length));
.replace(linkReg, match => ' '.repeat(match.length));

codes.push('<template>\n');
codes.push([content, undefined, 0]);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { FileCapabilities, FileRangeCapabilities } from '@volar/language-core';
import { VueLanguagePlugin } from '../types';

const customBlockReg = /^(.*)\.customBlock_([^_]+)_(\d+)\.([^.]+)$/;

const plugin: VueLanguagePlugin = () => {

return {
Expand All @@ -17,7 +19,7 @@ const plugin: VueLanguagePlugin = () => {
},

resolveEmbeddedFile(_fileName, sfc, embeddedFile) {
const match = embeddedFile.fileName.match(/^(.*)\.customBlock_([^_]+)_(\d+)\.([^.]+)$/);
const match = embeddedFile.fileName.match(customBlockReg);
if (match) {
const index = parseInt(match[3]);
const customBlock = sfc.customBlocks[index];
Expand Down
7 changes: 5 additions & 2 deletions packages/vue-language-core/src/plugins/vue-sfc-scripts.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { FileCapabilities, FileKind } from '@volar/language-core';
import { VueLanguagePlugin } from '../types';

const scriptFormatReg = /^(.*)\.script_format\.([^.]+)$/;
const scriptSetupFormatReg = /^(.*)\.scriptSetup_format\.([^.]+)$/;

const plugin: VueLanguagePlugin = () => {

return {
Expand All @@ -19,8 +22,8 @@ const plugin: VueLanguagePlugin = () => {
},

resolveEmbeddedFile(_fileName, sfc, embeddedFile) {
const scriptMatch = embeddedFile.fileName.match(/^(.*)\.script_format\.([^.]+)$/);
const scriptSetupMatch = embeddedFile.fileName.match(/^(.*)\.scriptSetup_format\.([^.]+)$/);
const scriptMatch = embeddedFile.fileName.match(scriptFormatReg);
const scriptSetupMatch = embeddedFile.fileName.match(scriptSetupFormatReg);
const script = scriptMatch ? sfc.script : scriptSetupMatch ? sfc.scriptSetup : undefined;
if (script) {
embeddedFile.kind = FileKind.TextFile;
Expand Down
4 changes: 3 additions & 1 deletion packages/vue-language-core/src/plugins/vue-sfc-styles.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { FileCapabilities, FileRangeCapabilities } from '@volar/language-core';
import { VueLanguagePlugin } from '../types';

const styleReg = /^(.*)\.style_(\d+)\.([^.]+)$/;

const plugin: VueLanguagePlugin = () => {

return {
Expand All @@ -17,7 +19,7 @@ const plugin: VueLanguagePlugin = () => {
},

resolveEmbeddedFile(_fileName, sfc, embeddedFile) {
const match = embeddedFile.fileName.match(/^(.*)\.style_(\d+)\.([^.]+)$/);
const match = embeddedFile.fileName.match(styleReg);
if (match) {
const index = parseInt(match[2]);
const style = sfc.styles[index];
Expand Down
4 changes: 3 additions & 1 deletion packages/vue-language-core/src/plugins/vue-sfc-template.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { FileCapabilities, FileRangeCapabilities } from '@volar/language-core';
import { VueLanguagePlugin } from '../types';

const templateReg = /^(.*)\.template\.([^.]+)$/;

const plugin: VueLanguagePlugin = () => {

return {
Expand All @@ -15,7 +17,7 @@ const plugin: VueLanguagePlugin = () => {
},

resolveEmbeddedFile(_fileName, sfc, embeddedFile) {
const match = embeddedFile.fileName.match(/^(.*)\.template\.([^.]+)$/);
const match = embeddedFile.fileName.match(templateReg);
if (match && sfc.template) {
embeddedFile.capabilities = FileCapabilities.full;
embeddedFile.content.push([
Expand Down
7 changes: 5 additions & 2 deletions packages/vue-language-core/src/plugins/vue-tsx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import { Sfc, VueLanguagePlugin } from '../types';
import { FileCapabilities, FileKind } from '@volar/language-core';
import * as muggle from 'muggle-string';

const templateFormatReg = /^\.template_format\.ts$/;
const templateStyleCssReg = /^\.template_style\.css$/;

const plugin: VueLanguagePlugin = ({ modules, vueCompilerOptions, compilerOptions, codegenStack }) => {

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

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

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

Expand Down
4 changes: 3 additions & 1 deletion packages/vue-language-core/src/sourceFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import { parseCssVars } from './utils/parseCssVars';
import { parseCssClassNames } from './utils/parseCssClassNames';
import { VueCompilerOptions } from './types';

const jsxReg = /^\.(js|ts)x?$/;

export class VueEmbeddedFile {

public parentFileName?: string;
Expand Down Expand Up @@ -52,7 +54,7 @@ export class VueFile implements VirtualFile {
}

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

get embeddedFiles() {
Expand Down
5 changes: 3 additions & 2 deletions packages/vue-language-core/src/utils/parseCssClassNames.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { clearComments } from './parseCssVars';

const cssClassNameReg = /(?=([\.]{1}[a-zA-Z_]+[\w\_\-]*)[\s\.\+\{\>#\:]{1})/g;

export function* parseCssClassNames(styleContent: string) {
styleContent = clearComments(styleContent);
const cssClassNameRegex = /(?=([\.]{1}[a-zA-Z_]+[\w\_\-]*)[\s\.\+\{\>#\:]{1})/g;
const matchs = styleContent.matchAll(cssClassNameRegex);
const matchs = styleContent.matchAll(cssClassNameReg);
for (const match of matchs) {
if (match.index !== undefined) {
const matchText = match[1];
Expand Down
12 changes: 8 additions & 4 deletions packages/vue-language-core/src/utils/parseCssVars.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
// https://github.com/vuejs/core/blob/main/packages/compiler-sfc/src/cssVars.ts#L47-L61

const vBindCssVarReg = /\bv-bind\(\s*(?:'([^']+)'|"([^"]+)"|([^'"][^)]*))\s*\)/g;
const commentReg1 = /\/\*([\s\S]*?)\*\//g;
const commentReg2 = /\/\/([\s\S]*?)\n/g;

export function* parseCssVars(styleContent: string) {
styleContent = clearComments(styleContent);
const reg = /\bv-bind\(\s*(?:'([^']+)'|"([^"]+)"|([^'"][^)]*))\s*\)/g;
const matchs = styleContent.matchAll(reg);
const matchs = styleContent.matchAll(vBindCssVarReg);
for (const match of matchs) {
if (match.index !== undefined) {
const matchText = match[1] ?? match[2] ?? match[3];
Expand All @@ -16,6 +20,6 @@ export function* parseCssVars(styleContent: string) {

export function clearComments(css: string) {
return css
.replace(/\/\*([\s\S]*?)\*\//g, match => `/*${' '.repeat(match.length - 4)}*/`)
.replace(/\/\/([\s\S]*?)\n/g, match => `//${' '.repeat(match.length - 3)}\n`);
.replace(commentReg1, match => `/*${' '.repeat(match.length - 4)}*/`)
.replace(commentReg2, match => `//${' '.repeat(match.length - 3)}\n`);
}
6 changes: 4 additions & 2 deletions packages/vue-language-service/src/languageService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ export function resolveConfig(
return config;
}

const unicodeReg = /\\u/g;

function resolvePlugins(
services: Config['services'],
vueCompilerOptions: VueCompilerOptions,
Expand Down Expand Up @@ -193,7 +195,7 @@ function resolvePlugins(
transformed = true;
item.additionalTextEdits.push({
range: editRange,
newText: unescape(printText.replace(/\\u/g, '%u')),
newText: unescape(printText.replace(unicodeReg, '%u')),
});
}
else if (exportDefault.args && exportDefault.argsNode) {
Expand All @@ -212,7 +214,7 @@ function resolvePlugins(
transformed = true;
item.additionalTextEdits.push({
range: editRange,
newText: unescape(printText.replace(/\\u/g, '%u')),
newText: unescape(printText.replace(unicodeReg, '%u')),
});
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ function isTsDocument(document: TextDocument) {
document.languageId === 'typescriptreact';
}

const charReg = /\w/;

export function isCharacterTyping(document: TextDocument, options: AutoInsertionContext) {

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

return /\w/.test(lastCharacter) && !/\w/.test(nextCharacter);
return charReg.test(lastCharacter) && !charReg.test(nextCharacter);
}

export function isBlacklistNode(ts: typeof import('typescript/lib/tsserverlibrary'), node: ts.Node, pos: number, allowAccessDotValue: boolean) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ const cmds = [
'vue-expect-error',
];

const directiveCommentReg = /<!--\s+@/;

const plugin: Service = (): ReturnType<Service> => {

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

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

Expand Down
Loading

0 comments on commit 15b57cd

Please sign in to comment.