diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/HighlightingColorizer.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/HighlightingColorizer.cs
index 870535a262..ee8df9d2a3 100644
--- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/HighlightingColorizer.cs
+++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/HighlightingColorizer.cs
@@ -106,6 +106,26 @@ namespace ICSharpCode.AvalonEdit.Highlighting
}
}
+ DocumentLine lastColorizedLine;
+
+ ///
+ protected override void Colorize(ITextRunConstructionContext context)
+ {
+ this.lastColorizedLine = null;
+ base.Colorize(context);
+ if (this.lastColorizedLine != context.VisualLine.LastDocumentLine) {
+ IHighlighter highlighter = context.TextView.Services.GetService(typeof(IHighlighter)) as IHighlighter;
+ if (highlighter != null) {
+ // In some cases, it is possible that we didn't highlight the last document line within the visual line
+ // (e.g. when the line ends with a fold marker).
+ // But even if we didn't highlight it, we'll have to update the highlighting state for it so that the
+ // proof inside TextViewDocumentHighlighter.OnHighlightStateChanged holds.
+ highlighter.GetSpanStack(context.VisualLine.LastDocumentLine.LineNumber);
+ }
+ }
+ this.lastColorizedLine = null;
+ }
+
///
protected override void ColorizeLine(DocumentLine line)
{
@@ -117,6 +137,7 @@ namespace ICSharpCode.AvalonEdit.Highlighting
visualLineElement => ApplyColorToElement(visualLineElement, section.Color));
}
}
+ this.lastColorizedLine = line;
}
///
@@ -140,6 +161,14 @@ namespace ICSharpCode.AvalonEdit.Highlighting
}
}
+ ///
+ /// This class is responsible for telling the TextView to redraw lines when the highlighting state has changed.
+ ///
+ ///
+ /// Creation of a VisualLine triggers the syntax highlighter (which works on-demand), so it says:
+ /// Hey, the user typed "/*". Don't just recreate that line, but also the next one
+ /// because my highlighting state (at end of line) changed!
+ ///
sealed class TextViewDocumentHighlighter : DocumentHighlighter
{
readonly TextView textView;
@@ -202,10 +231,23 @@ namespace ICSharpCode.AvalonEdit.Highlighting
// From this follows that the highlighting state at N is still up-to-date.
// The above proof holds even in the presence of folding: folding only ever hides text in the middle of a visual line.
- // The HighlightingColorizer will always be asked to highlight the LastDocumentLine of a visual line, so it will always
- // invalidate the next visual line when a folded line is constructed and the highlighting stack changed.
+ // Our Colorize-override ensures that the highlighting state is always updated for the LastDocumentLine,
+ // so it will always invalidate the next visual line when a folded line is constructed
+ // and the highlighting stack has changed.
textView.Redraw(line.NextLine, DispatcherPriority.Normal);
+
+ /*
+ * Meta-comment: "why does this have to be so complicated?"
+ *
+ * The problem is that I want to re-highlight only on-demand and incrementally;
+ * and at the same time only repaint changed lines.
+ * So the highlighter and the VisualLine construction both have to run in a single pass.
+ * The highlighter must take care that it never touches already constructed visual lines;
+ * if it detects that something must be redrawn because the highlighting state changed,
+ * it must do so early enough in the construction process.
+ * But doing it too early means it doesn't have the information necessary to re-highlight and redraw only the desired parts.
+ */
}
}
}
diff --git a/src/Main/Base/Project/Src/Util/WorkerThread.cs b/src/Main/Base/Project/Src/Util/WorkerThread.cs
index 1cac21637f..af831818f2 100644
--- a/src/Main/Base/Project/Src/Util/WorkerThread.cs
+++ b/src/Main/Base/Project/Src/Util/WorkerThread.cs
@@ -66,8 +66,13 @@ namespace ICSharpCode.SharpDevelop.Util
}
readonly object lockObject = new object();
+
+ // access needs lock using 'lockObject'
Queue taskQueue = new Queue();
+ // access needs lock using 'lockObject'
bool workerRunning;
+
+ // not a shared variable: accessed only within worker thread
bool exitWorker;
///