Skip to content

Commit 21ef28c

Browse files
committed
[html] update services, add folding for embedded css (for microsoft#47808)
1 parent e4c9755 commit 21ef28c

7 files changed

Lines changed: 79 additions & 227 deletions

File tree

extensions/html-language-features/server/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88
"node": "*"
99
},
1010
"dependencies": {
11-
"vscode-css-languageservice": "^3.0.8",
11+
"vscode-css-languageservice": "^3.0.9-next.6",
1212
"vscode-emmet-helper": "1.2.5",
13-
"vscode-html-languageservice": "^2.1.2",
13+
"vscode-html-languageservice": "^2.1.3-next.1",
1414
"vscode-languageserver": "^4.0.0",
1515
"vscode-languageserver-protocol-foldingprovider": "^1.0.1",
1616
"vscode-languageserver-types": "^3.6.1",

extensions/html-language-features/server/src/htmlServerMain.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import { formatError, runSafe, runSafeAsync } from './utils/runner';
2121
import { doComplete as emmetDoComplete, updateExtensionsPath as updateEmmetExtensionsPath, getEmmetCompletionParticipants } from 'vscode-emmet-helper';
2222

2323
import { FoldingRangesRequest, FoldingProviderServerCapabilities } from 'vscode-languageserver-protocol-foldingprovider';
24-
import { getFoldingRegions } from './modes/htmlFolding';
24+
import { getFoldingRanges } from './modes/htmlFolding';
2525

2626
namespace TagCloseRequest {
2727
export const type: RequestType<TextDocumentPositionParams, string | null, any, any> = new RequestType('html/tag');
@@ -465,7 +465,7 @@ connection.onRequest(FoldingRangesRequest.type, (params, token) => {
465465
return runSafe(() => {
466466
let document = documents.get(params.textDocument.uri);
467467
if (document) {
468-
return getFoldingRegions(languageModes, document, params.maxRanges, token);
468+
return getFoldingRanges(languageModes, document, params.maxRanges, token);
469469
}
470470
return null;
471471
}, null, `Error while computing folding regions for ${params.textDocument.uri}`, token);

extensions/html-language-features/server/src/modes/cssMode.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
import { LanguageModelCache, getLanguageModelCache } from '../languageModelCache';
88
import { TextDocument, Position, Range, CompletionList } from 'vscode-languageserver-types';
9-
import { getCSSLanguageService, Stylesheet, ICompletionParticipant } from 'vscode-css-languageservice';
9+
import { getCSSLanguageService, Stylesheet, ICompletionParticipant, FoldingRange } from 'vscode-css-languageservice';
1010
import { LanguageMode, Workspace } from './languageModes';
1111
import { HTMLDocumentRegions, CSS_STYLE_RULE } from './embeddedSupport';
1212
import { Color } from 'vscode-languageserver';
@@ -37,7 +37,7 @@ export function getCSSMode(documentRegions: LanguageModelCache<HTMLDocumentRegio
3737
if (typeof (<any>registeredCompletionParticipants[i]).getId === 'function' && (<any>registeredCompletionParticipants[i]).getId() === 'emmet') {
3838
const extractedResults = extractAbbreviation(document, position, { lookAhead: false, syntax: 'css' });
3939
if (extractedResults && extractedResults.abbreviation) {
40-
registeredCompletionParticipants[i].onCssProperty({ propertyName: extractedResults.abbreviation, range: extractedResults.abbreviationRange });
40+
registeredCompletionParticipants[i].onCssProperty!({ propertyName: extractedResults.abbreviation, range: extractedResults.abbreviationRange });
4141
}
4242
} else {
4343
nonEmmetCompletionParticipants.push(registeredCompletionParticipants[i]);
@@ -75,6 +75,11 @@ export function getCSSMode(documentRegions: LanguageModelCache<HTMLDocumentRegio
7575
let embedded = embeddedCSSDocuments.get(document);
7676
return cssLanguageService.getColorPresentations(embedded, cssStylesheets.get(embedded), color, range);
7777
},
78+
getFoldingRanges(document: TextDocument, range: Range): FoldingRange[] {
79+
let embedded = embeddedCSSDocuments.get(document);
80+
let ranges = cssLanguageService.getFoldingRanges(embedded, {}).ranges;
81+
return ranges.filter(r => r.startLine >= range.start.line && r.endLine < range.end.line);
82+
},
7883
onDocumentRemoved(document: TextDocument) {
7984
embeddedCSSDocuments.onDocumentRemoved(document);
8085
cssStylesheets.onDocumentRemoved(document);

extensions/html-language-features/server/src/modes/htmlFolding.ts

Lines changed: 3 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,11 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55
'use strict';
6-
import { TextDocument, CancellationToken, Position } from 'vscode-languageserver';
7-
import { LanguageService as HTMLLanguageService, TokenType, Range } from 'vscode-html-languageservice';
8-
9-
import { FoldingRangeType, FoldingRange, FoldingRangeList } from 'vscode-languageserver-protocol-foldingprovider';
6+
import { TextDocument, CancellationToken, Position, Range } from 'vscode-languageserver';
7+
import { FoldingRange, FoldingRangeList } from 'vscode-languageserver-protocol-foldingprovider';
108
import { LanguageModes } from './languageModes';
11-
import { binarySearch } from '../utils/arrays';
129

13-
export function getFoldingRegions(languageModes: LanguageModes, document: TextDocument, maxRanges: number | undefined, cancellationToken: CancellationToken | null): FoldingRangeList {
10+
export function getFoldingRanges(languageModes: LanguageModes, document: TextDocument, maxRanges: number | undefined, cancellationToken: CancellationToken | null): FoldingRangeList {
1411
let htmlMode = languageModes.getMode('html');
1512
let range = Range.create(Position.create(0, 0), Position.create(document.lineCount, 0));
1613
let ranges: FoldingRange[] = [];
@@ -92,94 +89,3 @@ function limitRanges(ranges: FoldingRange[], maxRanges: number) {
9289
}
9390
return ranges.filter((r, index) => (typeof nestingLevels[index] === 'number') && nestingLevels[index] < maxLevel);
9491
}
95-
96-
export const EMPTY_ELEMENTS: string[] = ['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr'];
97-
98-
export function isEmptyElement(e: string): boolean {
99-
return !!e && binarySearch(EMPTY_ELEMENTS, e.toLowerCase(), (s1: string, s2: string) => s1.localeCompare(s2)) >= 0;
100-
}
101-
102-
export function getHTMLFoldingRegions(htmlLanguageService: HTMLLanguageService, document: TextDocument, range: Range): FoldingRange[] {
103-
const scanner = htmlLanguageService.createScanner(document.getText());
104-
let token = scanner.scan();
105-
let ranges: FoldingRange[] = [];
106-
let stack: { startLine: number, tagName: string }[] = [];
107-
let lastTagName = null;
108-
let prevStart = -1;
109-
110-
function addRange(range: FoldingRange) {
111-
ranges.push(range);
112-
prevStart = range.startLine;
113-
}
114-
115-
while (token !== TokenType.EOS) {
116-
switch (token) {
117-
case TokenType.StartTag: {
118-
let tagName = scanner.getTokenText();
119-
let startLine = document.positionAt(scanner.getTokenOffset()).line;
120-
stack.push({ startLine, tagName });
121-
lastTagName = tagName;
122-
break;
123-
}
124-
case TokenType.EndTag: {
125-
lastTagName = scanner.getTokenText();
126-
break;
127-
}
128-
case TokenType.StartTagClose:
129-
if (!lastTagName || !isEmptyElement(lastTagName)) {
130-
break;
131-
}
132-
// fallthrough
133-
case TokenType.EndTagClose:
134-
case TokenType.StartTagSelfClose: {
135-
let i = stack.length - 1;
136-
while (i >= 0 && stack[i].tagName !== lastTagName) {
137-
i--;
138-
}
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-
}
148-
}
149-
break;
150-
}
151-
case TokenType.Comment: {
152-
let startLine = document.positionAt(scanner.getTokenOffset()).line;
153-
let text = scanner.getTokenText();
154-
let m = text.match(/^\s*#(region\b)|(endregion\b)/);
155-
if (m) {
156-
if (m[1]) { // start pattern match
157-
stack.push({ startLine, tagName: '' }); // empty tagName marks region
158-
} else {
159-
let i = stack.length - 1;
160-
while (i >= 0 && stack[i].tagName.length) {
161-
i--;
162-
}
163-
if (i >= 0) {
164-
let stackElement = stack[i];
165-
stack.length = i;
166-
let endLine = startLine;
167-
startLine = stackElement.startLine;
168-
if (endLine > startLine && prevStart !== startLine) {
169-
addRange({ startLine, endLine, type: FoldingRangeType.Region });
170-
}
171-
}
172-
}
173-
} else {
174-
let endLine = document.positionAt(scanner.getTokenOffset() + scanner.getTokenLength()).line;
175-
if (startLine < endLine) {
176-
addRange({ startLine, endLine, type: FoldingRangeType.Comment });
177-
}
178-
}
179-
break;
180-
}
181-
}
182-
token = scanner.scan();
183-
}
184-
return ranges;
185-
}

extensions/html-language-features/server/src/modes/htmlMode.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import { TextDocument, Position, Range, CompletionItem } from 'vscode-languagese
1010
import { LanguageMode, Workspace } from './languageModes';
1111

1212
import { FoldingRange } from 'vscode-languageserver-protocol-foldingprovider';
13-
import { getHTMLFoldingRegions } from './htmlFolding';
1413
import { getPathCompletionParticipant } from './pathCompletion';
1514

1615
export function getHTMLMode(htmlLanguageService: HTMLLanguageService, workspace: Workspace): LanguageMode {
@@ -65,9 +64,9 @@ export function getHTMLMode(htmlLanguageService: HTMLLanguageService, workspace:
6564
return htmlLanguageService.format(document, range, formatSettings);
6665
},
6766
getFoldingRanges(document: TextDocument, range: Range): FoldingRange[] {
68-
return getHTMLFoldingRegions(htmlLanguageService, document, range);
67+
let ranges = htmlLanguageService.getFoldingRanges(document).ranges;
68+
return ranges.filter(r => r.startLine >= range.start.line && r.endLine < range.end.line);
6969
},
70-
7170
doAutoClose(document: TextDocument, position: Position) {
7271
let offset = document.offsetAt(position);
7372
let text = document.getText();

0 commit comments

Comments
 (0)