Some scenarios, e.g. syntax highlighting, requires detecting location of specific text ranges - tokens (keywords, quoted strings, etc). This task requires parsing the current document and retrieving DocumentRange objects that correspond to each token in the document. Also, the remaining document content should be split on document ranges without any gap.
As a result, a lot of DocumentRange objects are created in the document model. RichEditControl tracks position of each created document range in order to update the DocumentRange object if the document is modified or the range is changed.
At the moment, the approach provided in the How to implement T-SQL language syntax highlighting by creating Syntax Highlight Tokens manually example works slowly with a lot of keywords and big files.
For instance, it takes approximately 1.5 minutes to open the 350 Kb XML file from the The SyntaxHighlightService operates slowly with a large XML file thread on my machine.
It would be great to improve the RichEditControl performance on operating with document ranges in future versions.
With this fix we implemented the DocumentRange.Freeze method that makes a DocumentRange object uneditable.
After this method is called, RichEditControl stops tracking the actual document position for this range. This allows you to significantly improve RichEditControl performance in scenarios where it is necessary to retrieve information from many document ranges, e.g., for syntax highlighting.
We tested the algorithm from the How to implement T-SQL language syntax highlighting by creating Syntax Highlight Tokens manually example with the 350 Kb XML file from the The SyntaxHighlightService operates slowly with a large XML file ticket with this fix.
Now it takes 3 seconds to open and highlight XML tags in this document. In version 19.1.5, execution of this operation took approximately 90 seconds in Release mode.
See the test project in the attachment.
Note that the document range cannot be modified after the DocumentRange.Freeze method is executed for this range. So, the frozen document range becomes invalid after the document is modified. Don't use this range for further document processing operations.
We also implemented the IEnumerable<DocumentRange> DocumentRangeExtensions.GetAsFrozen(this IEnumerable<DocumentRange> ranges) extension method to freeze multiple DocumentRange objects at once.
Here is a sample code snippet that demonstrates how to find the document ranges with keywords for syntax highlighting with the newly added API:
var ranges = document.FindAll(regex).GetAsFrozen();