AvalonEdit: Cascading HighlightingColorizers

The problem is that the HighlightingColorizer does not directly store a reference to the DocumentHighlighter, but instead stores it via TextView.Services. This is done to allow attaching the same colorizer to multiple editors, so that each editor gets its own DocumentHighlighter.

When you attach a second colorizer, it overwrites the IHighlighter stored in the service container; and both colorizers end up using the new highlighter.

Also, note that the 'copy to clipboard' logic in HtmlClipboard directly accesses the IHighlighter service, it does not use any colorizers. (copying text to Word preserves the syntax highlighting only, no other transformations like fold markers)

There are essentially two approaches to solve this issue:

  1. Do not store the additional highlighter as a service. You can do this by creating your own copy of the HighlightingColorizer class, and use a field in that class instead of accessing textView.Services. This is an easy change, but additional highlighters will not be used when copying text to the clipboard.

  2. Create an IHighlighter implementation that combines the HighlightedLines from multiple DocumentHighlighters. This is the approach we are using for the C# semantic highlighting in SharpDevelop 5, which works as an additional highlighter that extends the existing .xshd-based C# highlighting. However, this approach is complex (merging HighlightedLines is non-trivial given the ordering and nesting constraints on the sections), and requires an API change to the IHighlighter interface in order to deal with the OnHighlightStateChanged notification (AvalonEdit 4.x uses a derived class nested in HighlightingColorizer to get access to this callback; AvalonEdit 5.0 will use an event).