13
export class UnicodeTextModelHighlighter {
14
public static computeUnicodeHighlights(model: IUnicodeCharacterSearcherTarget, options: UnicodeHighlighterOptions, range?: IRange): IUnicodeHighlightsResult {
16
>
const endLine = range ? range.endLineNumber : model.getLineCount();
17
>
18
>
const codePointHighlighter = new CodePointHighlighter(options);
19
>
20
>
const candidates = codePointHighlighter.getCandidateCodePoints();
21
>
let regex: RegExp;
22
>
if (candidates === 'allNonBasicAscii') {
23
regex = new RegExp('[^\\t\\n\\r\\x20-\\x7E]', 'g');
25
>
regex = new RegExp(`${buildRegExpCharClassExpr(Array.from(candidates))}`, 'g');
26
>
}
27
>
28
>
const searcher = new Searcher(null, regex);
29
>
const ranges: Range[] = [];
30
>
let hasMore = false;
31
>
let m: RegExpExecArray | null;
32
>
33
>
let ambiguousCharacterCount = 0;
34
>
let invisibleCharacterCount = 0;
35
>
let nonBasicAsciiCharacterCount = 0;
36
>
37
>
forLoop:
38
>
for (let lineNumber = startLine, lineCount = endLine; lineNumber <= lineCount; lineNumber++) {
39
>
const lineContent = model.getLineContent(lineNumber);
40
>
const lineLength = lineContent.length;
41
>
42
>
// Reset regex to search from the beginning
43
>
searcher.reset(0);
44
>
do {
45
>
m = searcher.next(lineContent);
46
>
if (m) {
47
>
let startIndex = m.index;
48
>
let endIndex = m.index + m[0].length;
49
>
50
>
// Extend range to entire code point
51
>
if (startIndex > 0) {
52
>
const charCodeBefore = lineContent.charCodeAt(startIndex - 1);
53
>
if (strings.isHighSurrogate(charCodeBefore)) {
54
startIndex--;
55
}
57
>
if (endIndex + 1 < lineLength) {
58
>
const charCodeBefore = lineContent.charCodeAt(endIndex - 1);
59
>
if (strings.isHighSurrogate(charCodeBefore)) {
60
endIndex++;
61
}
63
>
const str = lineContent.substring(startIndex, endIndex);
64
>
let word = getWordAtText(startIndex + 1, DEFAULT_WORD_REGEXP, lineContent, 0);
65
>
if (word && word.endColumn <= startIndex + 1) {
66
>
// The word does not include the problematic character, ignore the word
67
>
word = null;
68
>
}
69
>
const highlightReason = codePointHighlighter.shouldHighlightNonBasicASCII(str, word ? word.word : null);
70
>
71
>
if (highlightReason !== SimpleHighlightReason.None) {
72
>
if (highlightReason === SimpleHighlightReason.Ambiguous) {
73
ambiguousCharacterCount++;
75
>
invisibleCharacterCount++;
76
>
} else if (highlightReason === SimpleHighlightReason.NonBasicASCII) {
77
nonBasicAsciiCharacterCount++;
78
} else {
79
assertNever(highlightReason);
80
}
82
>
const MAX_RESULT_LENGTH = 1000;
83
>
if (ranges.length >= MAX_RESULT_LENGTH) {
84
hasMore = true;
85
break forLoop;
86
}
88
>
ranges.push(new Range(lineNumber, startIndex + 1, lineNumber, endIndex + 1));
89
>
}
90
>
}
91
>
} while (m);
92
>
}
93
>
return {
94
>
ranges,
95
>
hasMore,
96
>
ambiguousCharacterCount,
97
>
invisibleCharacterCount,
98
>
nonBasicAsciiCharacterCount
99
>
};
100
>
}
101
102
public static computeUnicodeHighlightReason(char: string, options: UnicodeHighlighterOptions): UnicodeHighlighterReason | null {