Skip to content

Commit 5710ce9

Browse files
committed
[html] improve incomplete foldings (for microsoft#44712)
1 parent 1f9ab94 commit 5710ce9

2 files changed

Lines changed: 58 additions & 30 deletions

File tree

extensions/html/server/src/modes/htmlFolding.ts

Lines changed: 25 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -103,26 +103,22 @@ export function getHTMLFoldingRegions(htmlLanguageService: HTMLLanguageService,
103103
const scanner = htmlLanguageService.createScanner(document.getText());
104104
let token = scanner.scan();
105105
let ranges: FoldingRange[] = [];
106-
let stack: FoldingRange[] = [];
107-
let elementNames: string[] = [];
106+
let stack: { startLine: number, tagName: string }[] = [];
108107
let lastTagName = null;
109108
let prevStart = -1;
110109

111110
function addRange(range: FoldingRange) {
112111
ranges.push(range);
112+
prevStart = range.startLine;
113113
}
114114

115115
while (token !== TokenType.EOS) {
116116
switch (token) {
117-
case TokenType.StartTagOpen: {
118-
let startLine = document.positionAt(scanner.getTokenOffset()).line;
119-
let range = { startLine, endLine: startLine };
120-
stack.push(range);
121-
break;
122-
}
123117
case TokenType.StartTag: {
124-
lastTagName = scanner.getTokenText();
125-
elementNames.push(lastTagName);
118+
let tagName = scanner.getTokenText();
119+
let startLine = document.positionAt(scanner.getTokenOffset()).line;
120+
stack.push({ startLine, tagName });
121+
lastTagName = tagName;
126122
break;
127123
}
128124
case TokenType.EndTag: {
@@ -136,17 +132,19 @@ export function getHTMLFoldingRegions(htmlLanguageService: HTMLLanguageService,
136132
// fallthrough
137133
case TokenType.EndTagClose:
138134
case TokenType.StartTagSelfClose: {
139-
let name = elementNames.pop();
140-
let range = stack.pop();
141-
while (name && name !== lastTagName) {
142-
name = elementNames.pop();
143-
range = stack.pop();
135+
let i = stack.length - 1;
136+
while (i >= 0 && stack[i].tagName !== lastTagName) {
137+
i--;
144138
}
145-
let line = document.positionAt(scanner.getTokenOffset()).line;
146-
if (range && line > range.startLine + 1 && prevStart !== range.startLine) {
147-
range.endLine = line - 1;
148-
addRange(range);
149-
prevStart = range.startLine;
139+
if (i >= 0) {
140+
let stackElement = stack[i];
141+
stack.length = i;
142+
let line = document.positionAt(scanner.getTokenOffset()).line;
143+
let startLine = stackElement.startLine;
144+
let endLine = line - 1;
145+
if (endLine > startLine && prevStart !== startLine) {
146+
addRange({ startLine, endLine });
147+
}
150148
}
151149
break;
152150
}
@@ -156,29 +154,26 @@ export function getHTMLFoldingRegions(htmlLanguageService: HTMLLanguageService,
156154
let m = text.match(/^\s*#(region\b)|(endregion\b)/);
157155
if (m) {
158156
if (m[1]) { // start pattern match
159-
let range = { startLine, endLine: startLine, type: FoldingRangeType.Region };
160-
stack.push(range);
161-
elementNames.push('');
157+
stack.push({ startLine, tagName: '' }); // empty tagName marks region
162158
} else {
163159
let i = stack.length - 1;
164-
while (i >= 0 && stack[i].type !== FoldingRangeType.Region) {
160+
while (i >= 0 && stack[i].tagName.length) {
165161
i--;
166162
}
167163
if (i >= 0) {
168-
let range = stack[i];
164+
let stackElement = stack[i];
169165
stack.length = i;
170-
if (startLine > range.startLine && prevStart !== range.startLine) {
171-
range.endLine = startLine;
172-
addRange(range);
173-
prevStart = range.startLine;
166+
let endLine = startLine;
167+
startLine = stackElement.startLine;
168+
if (endLine > startLine && prevStart !== startLine) {
169+
addRange({ startLine, endLine, type: FoldingRangeType.Region });
174170
}
175171
}
176172
}
177173
} else {
178174
let endLine = document.positionAt(scanner.getTokenOffset() + scanner.getTokenLength()).line;
179175
if (startLine < endLine) {
180176
addRange({ startLine, endLine, type: FoldingRangeType.Comment });
181-
prevStart = startLine;
182177
}
183178
}
184179
break;

extensions/html/server/src/test/folding.test.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,39 @@ suite('Object Folding', () => {
188188
// assertRanges(input, [r(0, 7), r(1, 6), r(2, 5), r(3, 5, 'comment')]);
189189
// });
190190

191+
test('Fold incomplete', () => {
192+
let input = [
193+
/*0*/'<body>',
194+
/*1*/'<div></div>',
195+
/*2*/'Hello',
196+
/*3*/'</div>',
197+
/*4*/'</body>',
198+
];
199+
assertRanges(input, [r(0, 3)]);
200+
});
201+
202+
test('Fold incomplete 2', () => {
203+
let input = [
204+
/*0*/'<be><div>',
205+
/*1*/'<!-- #endregion -->',
206+
/*2*/'</div>',
207+
];
208+
assertRanges(input, [r(0, 1)]);
209+
});
210+
211+
test('Fold intersecting region', () => {
212+
let input = [
213+
/*0*/'<body>',
214+
/*1*/'<!-- #region -->',
215+
/*2*/'Hello',
216+
/*3*/'<div></div>',
217+
/*4*/'</body>',
218+
/*5*/'<!-- #endregion -->',
219+
];
220+
assertRanges(input, [r(0, 3)]);
221+
});
222+
223+
191224
test('Test limit', () => {
192225
let input = [
193226
/* 0*/'<div>',

0 commit comments

Comments
 (0)