execute method
Implementation
Map<String, Object?> execute(Map<String, Object?> request) {
final totalTimer = Stopwatch()..start();
final session = request['session']! as String;
final revision = request['revision']! as int;
final grammarName = request['grammar']! as String;
final fullSnapshot =
request.containsKey('source') || request.containsKey('sourceChunks');
final sameGrammar =
!fullSnapshot && _sessionGrammars[session] == grammarName;
final sourceTimer = Stopwatch()..start();
final resolved = _sourceFor(request, session, revision);
sourceTimer.stop();
final source = resolved.source;
final grammar = _grammars[grammarName];
if (grammar == null) {
throw StateError('Grammar $grammarName has not been loaded.');
}
final parser = _parserForSession(session, grammarName, grammar);
// Every mutation follows Tree-sitter's normal incremental path. Empty,
// one-character, and whole-document replacements are not separate parser
// modes: the edit is applied to the persistent tree just like any other
// replacement, allowing subsequent rapid edits to retain one coherent
// session base.
final previous = sameGrammar ? _trees[session] : null;
final previousSpans = sameGrammar ? _spanCaches[session] : null;
final treeEdits = resolved.edits;
final parseTimer = Stopwatch()..start();
final parsed = parser.parse(
source,
oldTree: previous,
edits: treeEdits,
annotateLocals: grammar.highlightsQuery.requiresLocalProperties,
);
parseTimer.stop();
_trees[session] = parsed;
_sessionGrammars[session] = grammarName;
final rangeTimer = Stopwatch()..start();
final highlightRange = previousSpans == null
? null
: _incrementalHighlightRange(source, parsed, resolved.edits);
rangeTimer.stop();
final queryTimer = Stopwatch()..start();
final spans = _highlightGrammar(
grammarName,
grammar,
_grammars,
parsed.rootNode,
source,
highlightRange,
);
queryTimer.stop();
final spliceTimer = Stopwatch()..start();
final queriedSpans = spans;
final workerSpans = previousSpans == null || highlightRange == null
? queriedSpans
: _spliceIncrementalSpans(
previousSpans,
queriedSpans,
resolved.edits,
highlightRange,
);
spliceTimer.stop();
final patchTimer = Stopwatch()..start();
final patch = _spanPatch(previousSpans, workerSpans);
patchTimer.stop();
_spanCaches[session] = workerSpans;
final scopes = <String>[];
final scopeIds = <String, int>{};
final packedSpans = Uint32List(patch.inserted.length * 5);
for (var index = 0; index < patch.inserted.length; index++) {
final span = patch.inserted[index];
final scope = scopeIds.putIfAbsent(span.scope, () {
scopes.add(span.scope);
return scopes.length - 1;
});
final output = index * 5;
packedSpans[output] = span.start;
packedSpans[output + 1] = span.end;
packedSpans[output + 2] = scope;
packedSpans[output + 3] = span.priority;
packedSpans[output + 4] = span.order;
}
final changedLinesTimer = Stopwatch()..start();
final changedLines = Uint32List.fromList(
_changedLines(source, previous, parsed),
);
changedLinesTimer.stop();
totalTimer.stop();
return <String, Object?>{
'revision': revision,
'sourceLength': source.length,
'rootKind': parsed.rootNode.kind,
'rootStartByte': parsed.rootNode.startByte,
'rootEndByte': parsed.rootNode.endByte,
'rootHasError': parsed.rootNode.hasError,
'reusedNodeCount': parsed.reusedNodeCount,
'lexedTokenCount': parsed.generatedTree?.lexedTokenCount ?? 0,
'parsePassCount': parsed.generatedTree?.parsePassCount ?? 0,
'parserInstanceId': _parserInstanceIds[(session, grammarName)],
'parserCreationCount': _parserCreationCounts[session],
'lexedBytes': parsed.lexedBytes,
'reusedBytes': parsed.reusedBytes,
'parseActionCount': parsed.parseActionCount,
'reuseCursorVisitCount': parsed.reuseCursorVisitCount,
'firstLexedByte': parsed.generatedTree?.firstLexedByte,
'lastLexedByte': parsed.generatedTree?.lastLexedByte,
'reuseRejections': parsed.generatedTree?.reuseRejections ?? const {},
'queriedUtf16Length': highlightRange?.length ?? source.length,
'scopes': scopes,
'packedSpans': packedSpans,
'spanPatchStart': patch.start,
'spanPatchRemove': patch.removeCount,
'spanPatchSuffixShift': patch.suffixShift,
'isSpanPatch': previousSpans != null,
'changedLines': changedLines,
'phaseTimingsMicros': <String, int>{
'source': sourceTimer.elapsedMicroseconds,
'parseAndConvert': parseTimer.elapsedMicroseconds,
'range': rangeTimer.elapsedMicroseconds,
'queryAndSort': queryTimer.elapsedMicroseconds,
'splice': spliceTimer.elapsedMicroseconds,
'patch': patchTimer.elapsedMicroseconds,
'changedLines': changedLinesTimer.elapsedMicroseconds,
'total': totalTimer.elapsedMicroseconds,
for (final entry in parsed.phaseTimingsMicros.entries)
'parse.${entry.key}': entry.value,
},
};
}