HighlightedDiff.of constructor
HighlightedDiff.of(
- FileDiff diff, {
- required Highlighter highlighter,
- required SyntaxTheme theme,
- String? language,
- Duration? budget,
Highlights diff. The language comes from language if given,
otherwise from the file extension. Unknown languages stay plain.
With a budget, full texts are tokenized for at most that long, and
tokenize continues. Lines not tokenized yet are plain.
Implementation
factory HighlightedDiff.of(
FileDiff diff, {
required Highlighter highlighter,
required SyntaxTheme theme,
String? language,
Duration? budget,
}) {
final grammar = _grammarFor(diff, highlighter, language);
if (grammar == null) {
// Plain: each line is one token, made when it's asked for.
return HighlightedDiff._(
theme,
const {},
const {},
oldPlain: _textOf(diff, old: true),
newPlain: _textOf(diff, old: false),
);
}
final oldLines = diff.oldLines;
final newLines = diff.newLines;
if (oldLines != null && newLines != null) {
final highlighted = HighlightedDiff._(
theme,
const {},
const {},
oldDocument: TokenizedDocument(grammar),
newDocument: TokenizedDocument(grammar),
);
final clock = Stopwatch()..start();
highlighted._newDocument!.update(newLines.join('\n'), budget: budget);
highlighted._oldDocument!.update(
oldLines.join('\n'),
budget: _left(budget, clock),
);
return highlighted;
}
final old = <int, List<ThemedToken>>{};
final newer = <int, List<ThemedToken>>{};
void tokenize(
Iterable<(int, String)> numbered,
Map<int, List<ThemedToken>> out,
) {
StateStack? state;
for (final (number, text) in numbered) {
final tokens = grammar.tokenizeLine(text, state);
state = tokens.endState;
out[number] = themeTokens(text, tokens.tokens, theme);
}
}
for (final hunk in diff.hunks) {
tokenize([
for (final l in hunk.lines)
if (_onSide(l, old: true)) (l.oldNumber!, l.text),
], old);
tokenize([
for (final l in hunk.lines)
if (_onSide(l, old: false)) (l.newNumber!, l.text),
], newer);
}
return HighlightedDiff._(theme, old, newer);
}