[html] syntax folding (disabled by default)

This commit is contained in:
Martin Aeschlimann
2018-02-23 16:23:45 +01:00
parent 61a2adfa1a
commit 3e7521b68e
8 changed files with 323 additions and 4 deletions

View File

@@ -9,6 +9,8 @@ import { LanguageService as HTMLLanguageService, HTMLDocument, DocumentContext,
import { TextDocument, Position, Range } from 'vscode-languageserver-types';
import { LanguageMode, Settings } from './languageModes';
import { FoldingRangeType, FoldingRange, FoldingRangeList } from '../protocol/foldingProvider.proposed';
export function getHTMLMode(htmlLanguageService: HTMLLanguageService): LanguageMode {
let globalSettings: Settings = {};
let htmlDocuments = getLanguageModelCache<HTMLDocument>(10, 60, document => htmlLanguageService.parseHTMLDocument(document));
@@ -71,6 +73,80 @@ export function getHTMLMode(htmlLanguageService: HTMLLanguageService): LanguageM
formatSettings = merge(formatParams, formatSettings);
return htmlLanguageService.format(document, range, formatSettings);
},
getFoldingRanges(document: TextDocument): FoldingRangeList {
const scanner = htmlLanguageService.createScanner(document.getText());
let token = scanner.scan();
let ranges: FoldingRange[] = [];
let stack: FoldingRange[] = [];
let elementNames: string[] = [];
let lastTagName = null;
let prevStart = -1;
while (token !== TokenType.EOS) {
switch (token) {
case TokenType.StartTagOpen: {
let startLine = document.positionAt(scanner.getTokenOffset()).line;
let range = { startLine, endLine: startLine };
stack.push(range);
break;
}
case TokenType.StartTag: {
lastTagName = scanner.getTokenText();
elementNames.push(lastTagName);
break;
}
case TokenType.EndTag: {
lastTagName = scanner.getTokenText();
break;
}
case TokenType.EndTagClose:
case TokenType.StartTagSelfClose: {
let name = elementNames.pop();
let range = stack.pop();
while (name && name !== lastTagName) {
name = elementNames.pop();
range = stack.pop();
}
let line = document.positionAt(scanner.getTokenOffset()).line;
if (range && line > range.startLine + 1 && prevStart !== range.startLine) {
range.endLine = line - 1;
ranges.push(range);
prevStart = range.startLine;
}
break;
}
case TokenType.Comment: {
let text = scanner.getTokenText();
let m = text.match(/^\s*#(region\b)|(endregion\b)/);
if (m) {
let line = document.positionAt(scanner.getTokenOffset()).line;
if (m[1]) { // start pattern match
let range = { startLine: line, endLine: line, type: FoldingRangeType.Region };
stack.push(range);
elementNames.push('');
} else {
let i = stack.length - 1;
while (i >= 0 && stack[i].type !== FoldingRangeType.Region) {
i--;
}
if (i >= 0) {
let range = stack[i];
stack.length = i;
if (line > range.startLine && prevStart !== range.startLine) {
range.endLine = line;
ranges.push(range);
prevStart = range.startLine;
}
}
}
}
break;
}
}
token = scanner.scan();
}
return <FoldingRangeList>{ ranges };
},
doAutoClose(document: TextDocument, position: Position) {
let offset = document.offsetAt(position);
let text = document.getText();