Skip to content

Commit 5e4bc95

Browse files
committed
Hitting return after </button> element crashes VS Code (Insiders). Fixes microsoft#135806
1 parent dc1a669 commit 5e4bc95

File tree

2 files changed

+37
-10
lines changed

2 files changed

+37
-10
lines changed

extensions/html-language-features/server/src/test/words.test.ts

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,32 @@
44
*--------------------------------------------------------------------------------------------*/
55
import * as assert from 'assert';
66
import * as words from '../utils/strings';
7+
import * as fs from 'fs';
8+
import * as path from 'path';
79

8-
suite('HTML Words', () => {
10+
suite('HTML Language Configuration', () => {
11+
const config = JSON.parse((fs.readFileSync(path.join(__dirname, '../../../../html/language-configuration.json')).toString()));
912

10-
let wordRegex = /(-?\d*\.\d\w*)|([^\`\~\!\@\#\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g;
13+
function createRegex(str: string | { pattern: string, flags: string }): RegExp {
14+
if (typeof str === 'string') {
15+
return new RegExp(str, 'g');
16+
}
17+
return new RegExp(str.pattern, str.flags);
18+
}
19+
20+
const wordRegex = createRegex(config.wordPattern);
1121

1222
function assertWord(value: string, expected: string): void {
13-
let offset = value.indexOf('|');
14-
value = value.substr(0, offset) + value.substr(offset + 1);
23+
const offset = value.indexOf('|');
24+
value = value.substr(0, offset) + value.substring(offset + 1);
1525

16-
let actualRange = words.getWordAtText(value, offset, wordRegex);
26+
const actualRange = words.getWordAtText(value, offset, wordRegex);
1727
assert(actualRange.start <= offset);
1828
assert(actualRange.start + actualRange.length >= offset);
1929
assert.strictEqual(value.substr(actualRange.start, actualRange.length), expected);
2030
}
2131

22-
23-
test('Basic', function (): any {
32+
test('Words Basic', function (): any {
2433
assertWord('|var x1 = new F<A>(a, b);', 'var');
2534
assertWord('v|ar x1 = new F<A>(a, b);', 'var');
2635
assertWord('var| x1 = new F<A>(a, b);', 'var');
@@ -35,10 +44,28 @@ suite('HTML Words', () => {
3544
assertWord('var x1 = | new F<A>(a, b)|;|', '');
3645
});
3746

38-
test('Multiline', function (): any {
47+
test('Words Multiline', function (): any {
3948
assertWord('console.log("hello");\n|var x1 = new F<A>(a, b);', 'var');
4049
assertWord('console.log("hello");\n|\nvar x1 = new F<A>(a, b);', '');
4150
assertWord('console.log("hello");\n\r |var x1 = new F<A>(a, b);', 'var');
4251
});
4352

53+
const onEnterBeforeRules: RegExp[] = config.onEnterRules.map((r: any) => createRegex(r.beforeText));
54+
55+
function assertBeforeRule(text: string, expectedMatch: boolean): void {
56+
for (const reg of onEnterBeforeRules) {
57+
const start = new Date().getTime();
58+
assert.strictEqual(reg.test(text), expectedMatch);
59+
const totalTime = new Date().getTime() - start;
60+
assert.ok(totalTime < 200, `Evaluation of ${reg.source} on ${text} took ${totalTime}ms]`);
61+
}
62+
}
63+
64+
test('OnEnter Before', function (): any {
65+
assertBeforeRule('<button attr1=val1 attr2=val2', false);
66+
assertBeforeRule('<button attr1=val1 attr2=val2>', true);
67+
assertBeforeRule('<button attr1=\'val1\' attr2="val2">', true);
68+
assertBeforeRule('<button attr1=val1 attr2=val2></button>', false);
69+
});
70+
4471
});

extensions/html/language-configuration.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,14 @@
3535
"wordPattern": "(-?\\d*\\.\\d\\w*)|([^\\`\\~\\!\\@\\$\\^\\&\\*\\(\\)\\=\\+\\[\\{\\]\\}\\\\\\|\\;\\:\\'\\\"\\,\\.\\<\\>\\/\\s]+)",
3636
"onEnterRules": [
3737
{
38-
"beforeText": { "pattern": "<(?!(?:area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr))([_:\\w][_:\\w-.\\d]*)(([^'\"/>]+|\"[^\"]*\"|'[^']*')*(?!\\/)>)[^<]*$", "flags": "i" },
38+
"beforeText": { "pattern": "<(?!(?:area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr))([_:\\w][_:\\w-.\\d]*)(?:(?:[^'\"/>]|\"[^\"]*\"|'[^']*')*?(?!\\/)>)[^<]*$", "flags": "i" },
3939
"afterText": { "pattern": "^<\\/([_:\\w][_:\\w-.\\d]*)\\s*>", "flags": "i" },
4040
"action": {
4141
"indent": "indentOutdent"
4242
}
4343
},
4444
{
45-
"beforeText": { "pattern": "<(?!(?:area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr))([_:\\w][_:\\w-.\\d]*)(([^'\"/>]+|\"[^\"]*\"|'[^']*')*(?!\\/)>)[^<]*$", "flags": "i" },
45+
"beforeText": { "pattern": "<(?!(?:area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr))([_:\\w][_:\\w-.\\d]*)(?:(?:[^'\"/>]|\"[^\"]*\"|'[^']*')*?(?!\\/)>)[^<]*$", "flags": "i" },
4646
"action": {
4747
"indent": "indent"
4848
}

0 commit comments

Comments
 (0)