Skip to content

Commit 08a65dc

Browse files
committed
Fix errors shown when having #endregion but not matching #region
1 parent 22ff8ef commit 08a65dc

File tree

2 files changed

+53
-28
lines changed

2 files changed

+53
-28
lines changed

src/services/cssFolding.ts

Lines changed: 34 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ function computeFoldingRanges(document: TextDocument): FoldingRange[] {
5555

5656
const ranges: FoldingRange[] = [];
5757

58-
const rangeDelimiterStack: Delimiter[] = [];
58+
const delimiterStack: Delimiter[] = [];
5959

6060
const scanner = getScanner();
6161
scanner.ignoreComment = false;
@@ -68,16 +68,19 @@ function computeFoldingRanges(document: TextDocument): FoldingRange[] {
6868
case TokenType.CurlyL:
6969
case InterpolationFunction:
7070
{
71-
rangeDelimiterStack.push({ line: getStartLine(token), type: 'brace', isStart: true });
71+
delimiterStack.push({ line: getStartLine(token), type: 'brace', isStart: true });
7272
break;
7373
}
7474
case TokenType.CurlyR: {
75-
if (rangeDelimiterStack.length !== 0) {
76-
const { line: startLine, type } = popPreviousStartDelimiterOfType(rangeDelimiterStack, 'brace');
75+
if (delimiterStack.length !== 0) {
76+
const prevDelimiter = popPrevStartDelimiterOfType(delimiterStack, 'brace');
77+
if (!prevDelimiter) {
78+
break;
79+
}
7780

7881
let endLine = getEndLine(token);
7982

80-
if (type === 'brace') {
83+
if (prevDelimiter.type === 'brace') {
8184
/**
8285
* Other than the case when curly brace is not on a new line by itself, for example
8386
* .foo {
@@ -88,9 +91,9 @@ function computeFoldingRanges(document: TextDocument): FoldingRange[] {
8891
endLine--;
8992
}
9093

91-
if (startLine !== endLine) {
94+
if (prevDelimiter.line !== endLine) {
9295
ranges.push({
93-
startLine,
96+
startLine: prevDelimiter.line,
9497
endLine,
9598
kind: undefined
9699
});
@@ -104,40 +107,43 @@ function computeFoldingRanges(document: TextDocument): FoldingRange[] {
104107
* All comments are marked as `Comment`
105108
*/
106109
case TokenType.Comment: {
107-
const commentRegionMarkerToRangeDelimiter = (marker): Delimiter => {
110+
const commentRegionMarkerToDelimiter = (marker): Delimiter => {
108111
if (marker === '#region') {
109112
return { line: getStartLine(token), type: 'comment', isStart: true };
110113
} else {
111114
return { line: getEndLine(token), type: 'comment', isStart: false };
112115
}
113116
};
114117

115-
let rangeDelimiter: Delimiter;
116-
117-
// /* */ comment region folding
118-
const matches = token.text.match(/^\s*\/\*\s*(#region|#endregion)\b\s*(.*?)\s*\*\//);
119-
if (matches) {
120-
rangeDelimiter = commentRegionMarkerToRangeDelimiter(matches[1]);
121-
} else if (document.languageId === 'scss' || document.languageId === 'less') {
122-
const matches = token.text.match(/^\s*\/\/\s*(#region|#endregion)\b\s*(.*?)\s*/);
118+
const getCurrDelimiter = (token: IToken): Delimiter => {
119+
const matches = token.text.match(/^\s*\/\*\s*(#region|#endregion)\b\s*(.*?)\s*\*\//);
123120
if (matches) {
124-
rangeDelimiter = commentRegionMarkerToRangeDelimiter(matches[1]);
121+
return commentRegionMarkerToDelimiter(matches[1]);
122+
} else if (document.languageId === 'scss' || document.languageId === 'less') {
123+
const matches = token.text.match(/^\s*\/\/\s*(#region|#endregion)\b\s*(.*?)\s*/);
124+
if (matches) {
125+
return commentRegionMarkerToDelimiter(matches[1]);
126+
}
125127
}
126-
}
127128

129+
return null;
130+
};
131+
132+
const currDelimiter = getCurrDelimiter(token);
133+
134+
// /* */ comment region folding
128135
// All #region and #endregion cases
129-
if (rangeDelimiter) {
130-
if (rangeDelimiter.isStart) {
131-
rangeDelimiterStack.push(rangeDelimiter);
136+
if (currDelimiter) {
137+
if (currDelimiter.isStart) {
138+
delimiterStack.push(currDelimiter);
132139
} else {
133-
const { line: startLine, type } = popPreviousStartDelimiterOfType(rangeDelimiterStack, 'comment');
140+
const prevDelimiter = popPrevStartDelimiterOfType(delimiterStack, 'comment');
134141

135-
const endLine = rangeDelimiter.line;
136-
if (type === 'comment') {
137-
if (startLine !== endLine) {
142+
if (prevDelimiter.type === 'comment') {
143+
if (prevDelimiter.line !== currDelimiter.line) {
138144
ranges.push({
139-
startLine,
140-
endLine,
145+
startLine: prevDelimiter.line,
146+
endLine: currDelimiter.line,
141147
kind: 'region'
142148
});
143149
}
@@ -163,7 +169,7 @@ function computeFoldingRanges(document: TextDocument): FoldingRange[] {
163169
return ranges;
164170
}
165171

166-
function popPreviousStartDelimiterOfType(stack: Delimiter[], type: DelimiterType): Delimiter {
172+
function popPrevStartDelimiterOfType(stack: Delimiter[], type: DelimiterType): Delimiter | null {
167173
if (stack.length === 0) {
168174
return null;
169175
}

src/test/css/folding.test.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,25 @@ suite('CSS Folding - Partial', () => {
119119
];
120120
assertRanges(input, [r(1, 4), r(2, 3)]);
121121
});
122+
123+
test('Without opening curly brace should not throw error', () => {
124+
const input = [
125+
/*0*/'.foo',
126+
/*1*/' color: blue;',
127+
/*2*/'}}'
128+
];
129+
assertRanges(input, []);
130+
});
131+
132+
// test('Without opening #region should not throw error', () => {
133+
// const input = [
134+
// /*0*/'.foo',
135+
// /*1*/' color: blue;',
136+
// /*2*/'}',
137+
// /*3*/'/* #endregion */'
138+
// ];
139+
// assertRanges(input, []);
140+
// });
122141
});
123142

124143
suite('CSS Folding - Comments', () => {

0 commit comments

Comments
 (0)