From 5e4bc951cd688ee8c4b4ddd9659253ab7f26079e Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Tue, 26 Oct 2021 11:55:47 +0200 Subject: [PATCH] Hitting return after element crashes VS Code (Insiders). Fixes #135806 --- .../server/src/test/words.test.ts | 43 +++++++++++++++---- extensions/html/language-configuration.json | 4 +- 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/extensions/html-language-features/server/src/test/words.test.ts b/extensions/html-language-features/server/src/test/words.test.ts index f86ae969c66..95ed0f8e231 100644 --- a/extensions/html-language-features/server/src/test/words.test.ts +++ b/extensions/html-language-features/server/src/test/words.test.ts @@ -4,23 +4,32 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; import * as words from '../utils/strings'; +import * as fs from 'fs'; +import * as path from 'path'; -suite('HTML Words', () => { +suite('HTML Language Configuration', () => { + const config = JSON.parse((fs.readFileSync(path.join(__dirname, '../../../../html/language-configuration.json')).toString())); - let wordRegex = /(-?\d*\.\d\w*)|([^\`\~\!\@\#\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g; + function createRegex(str: string | { pattern: string, flags: string }): RegExp { + if (typeof str === 'string') { + return new RegExp(str, 'g'); + } + return new RegExp(str.pattern, str.flags); + } + + const wordRegex = createRegex(config.wordPattern); function assertWord(value: string, expected: string): void { - let offset = value.indexOf('|'); - value = value.substr(0, offset) + value.substr(offset + 1); + const offset = value.indexOf('|'); + value = value.substr(0, offset) + value.substring(offset + 1); - let actualRange = words.getWordAtText(value, offset, wordRegex); + const actualRange = words.getWordAtText(value, offset, wordRegex); assert(actualRange.start <= offset); assert(actualRange.start + actualRange.length >= offset); assert.strictEqual(value.substr(actualRange.start, actualRange.length), expected); } - - test('Basic', function (): any { + test('Words Basic', function (): any { assertWord('|var x1 = new F(a, b);', 'var'); assertWord('v|ar x1 = new F(a, b);', 'var'); assertWord('var| x1 = new F(a, b);', 'var'); @@ -35,10 +44,28 @@ suite('HTML Words', () => { assertWord('var x1 = | new F(a, b)|;|', ''); }); - test('Multiline', function (): any { + test('Words Multiline', function (): any { assertWord('console.log("hello");\n|var x1 = new F(a, b);', 'var'); assertWord('console.log("hello");\n|\nvar x1 = new F(a, b);', ''); assertWord('console.log("hello");\n\r |var x1 = new F(a, b);', 'var'); }); + const onEnterBeforeRules: RegExp[] = config.onEnterRules.map((r: any) => createRegex(r.beforeText)); + + function assertBeforeRule(text: string, expectedMatch: boolean): void { + for (const reg of onEnterBeforeRules) { + const start = new Date().getTime(); + assert.strictEqual(reg.test(text), expectedMatch); + const totalTime = new Date().getTime() - start; + assert.ok(totalTime < 200, `Evaluation of ${reg.source} on ${text} took ${totalTime}ms]`); + } + } + + test('OnEnter Before', function (): any { + assertBeforeRule('', false); + }); + }); diff --git a/extensions/html/language-configuration.json b/extensions/html/language-configuration.json index ae03ea23623..628396b0918 100644 --- a/extensions/html/language-configuration.json +++ b/extensions/html/language-configuration.json @@ -35,14 +35,14 @@ "wordPattern": "(-?\\d*\\.\\d\\w*)|([^\\`\\~\\!\\@\\$\\^\\&\\*\\(\\)\\=\\+\\[\\{\\]\\}\\\\\\|\\;\\:\\'\\\"\\,\\.\\<\\>\\/\\s]+)", "onEnterRules": [ { - "beforeText": { "pattern": "<(?!(?:area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr))([_:\\w][_:\\w-.\\d]*)(([^'\"/>]+|\"[^\"]*\"|'[^']*')*(?!\\/)>)[^<]*$", "flags": "i" }, + "beforeText": { "pattern": "<(?!(?:area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr))([_:\\w][_:\\w-.\\d]*)(?:(?:[^'\"/>]|\"[^\"]*\"|'[^']*')*?(?!\\/)>)[^<]*$", "flags": "i" }, "afterText": { "pattern": "^<\\/([_:\\w][_:\\w-.\\d]*)\\s*>", "flags": "i" }, "action": { "indent": "indentOutdent" } }, { - "beforeText": { "pattern": "<(?!(?:area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr))([_:\\w][_:\\w-.\\d]*)(([^'\"/>]+|\"[^\"]*\"|'[^']*')*(?!\\/)>)[^<]*$", "flags": "i" }, + "beforeText": { "pattern": "<(?!(?:area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr))([_:\\w][_:\\w-.\\d]*)(?:(?:[^'\"/>]|\"[^\"]*\"|'[^']*')*?(?!\\/)>)[^<]*$", "flags": "i" }, "action": { "indent": "indent" }