8000 perf: hoist regexp if possible by so1ve · Pull Request #3378 · vuejs/language-tools · GitHub
[go: up one dir, main page]

Skip to content

perf: hoist regexp if possible #3378

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
perf: hoist regexp as possible
  • Loading branch information
so1ve committed Jul 7, 2023
commit 15b57cd05880d7d044acbd5d60c5a2d6d823c5b4
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