From d62fa46b7fd45abfe5119828ce6a72a931b2a930 Mon Sep 17 00:00:00 2001 From: Daniel Date: Tue, 22 Feb 2022 11:39:32 +0100 Subject: [PATCH] Try/catch exceptions for override methods and events. It prevents app crashes --- .../GenericLineTransformer.cs | 18 +++++- src/AvaloniaEdit.TextMate/TextMate.cs | 3 +- .../TextMateColoringTransformer.cs | 55 +++++++++++++------ .../TextTransformation.cs | 48 +++++++++------- 4 files changed, 85 insertions(+), 39 deletions(-) diff --git a/src/AvaloniaEdit.TextMate/GenericLineTransformer.cs b/src/AvaloniaEdit.TextMate/GenericLineTransformer.cs index e05d1f82..1aa95f18 100644 --- a/src/AvaloniaEdit.TextMate/GenericLineTransformer.cs +++ b/src/AvaloniaEdit.TextMate/GenericLineTransformer.cs @@ -1,3 +1,5 @@ +using System; + using Avalonia.Media; using AvaloniaEdit.Document; using AvaloniaEdit.Rendering; @@ -6,9 +8,23 @@ namespace AvaloniaEdit.TextMate { public abstract class GenericLineTransformer : DocumentColorizingTransformer { + private Action _exceptionHandler; + + public GenericLineTransformer(Action exceptionHandler) + { + _exceptionHandler = exceptionHandler; + } + protected override void ColorizeLine(DocumentLine line) { - TransformLine(line, CurrentContext); + try + { + TransformLine(line, CurrentContext); + } + catch (Exception ex) + { + _exceptionHandler?.Invoke(ex); + } } protected abstract void TransformLine(DocumentLine line, ITextRunConstructionContext context); diff --git a/src/AvaloniaEdit.TextMate/TextMate.cs b/src/AvaloniaEdit.TextMate/TextMate.cs index 7d860a1e..840a64ee 100644 --- a/src/AvaloniaEdit.TextMate/TextMate.cs +++ b/src/AvaloniaEdit.TextMate/TextMate.cs @@ -108,7 +108,8 @@ TextMateColoringTransformer GetOrCreateTransformer() if (transformer is null) { - transformer = new TextMateColoringTransformer(_editor.TextArea.TextView); + transformer = new TextMateColoringTransformer( + _editor.TextArea.TextView, _exceptionHandler); _editor.TextArea.TextView.LineTransformers.Add(transformer); } diff --git a/src/AvaloniaEdit.TextMate/TextMateColoringTransformer.cs b/src/AvaloniaEdit.TextMate/TextMateColoringTransformer.cs index 88d6213c..d8f94afd 100644 --- a/src/AvaloniaEdit.TextMate/TextMateColoringTransformer.cs +++ b/src/AvaloniaEdit.TextMate/TextMateColoringTransformer.cs @@ -23,6 +23,7 @@ public class TextMateColoringTransformer : private TMModel _model; private TextDocument _document; private TextView _textView; + private Action _exceptionHandler; private volatile int _firstVisibleLineIndex = -1; private volatile int _lastVisibleLineIndex = -1; @@ -30,9 +31,14 @@ public class TextMateColoringTransformer : private readonly Dictionary _brushes; private TextSegmentCollection _transformations; - public TextMateColoringTransformer(TextView textView) + public TextMateColoringTransformer( + TextView textView, + Action exceptionHandler) + : base(exceptionHandler) { _textView = textView; + _exceptionHandler = exceptionHandler; + _brushes = new Dictionary(); _textView.VisualLinesChanged += TextView_VisualLinesChanged; } @@ -51,11 +57,18 @@ public void SetModel(TextDocument document, TMModel model) private void TextView_VisualLinesChanged(object sender, EventArgs e) { - if (!_textView.VisualLinesValid || _textView.VisualLines.Count == 0) - return; + try + { + if (!_textView.VisualLinesValid || _textView.VisualLines.Count == 0) + return; - _firstVisibleLineIndex = _textView.VisualLines[0].FirstDocumentLine.LineNumber - 1; - _lastVisibleLineIndex = _textView.VisualLines[_textView.VisualLines.Count - 1].LastDocumentLine.LineNumber - 1; + _firstVisibleLineIndex = _textView.VisualLines[0].FirstDocumentLine.LineNumber - 1; + _lastVisibleLineIndex = _textView.VisualLines[_textView.VisualLines.Count - 1].LastDocumentLine.LineNumber - 1; + } + catch (Exception ex) + { + _exceptionHandler?.Invoke(ex); + } } public void Dispose() @@ -103,21 +116,31 @@ IBrush ForegroundTextTransformation.IColorMap.GetBrush(int colorId) protected override void TransformLine(DocumentLine line, ITextRunConstructionContext context) { - int i = line.LineNumber; + try + { + if (_model == null) + return; - var tokens = _model.GetLineTokens(i - 1); + int i = line.LineNumber; - if (tokens == null) - return; + var tokens = _model.GetLineTokens(i - 1); - RemoveLineTransformations(i); - ProcessTokens(i, tokens); + if (tokens == null) + return; - var transformsInLine = _transformations.FindOverlappingSegments(line); + RemoveLineTransformations(i); + ProcessTokens(i, tokens); - foreach (var transform in transformsInLine) + var transformsInLine = _transformations.FindOverlappingSegments(line); + + foreach (var transform in transformsInLine) + { + transform.Transform(this, line); + } + } + catch (Exception ex) { - transform.Transform(this, line); + _exceptionHandler?.Invoke(ex); } } @@ -154,7 +177,7 @@ private void ProcessTokens(int lineNumber, List tokens) fontStyle = themeRule.fontStyle; } - _transformations.Add(new ForegroundTextTransformation(this, lineOffset + startIndex, + _transformations.Add(new ForegroundTextTransformation(this, _exceptionHandler, lineOffset + startIndex, lineOffset + endIndex, foreground, background, fontStyle)); } } @@ -175,7 +198,7 @@ public void ModelTokensChanged(ModelTokensChangedEvent e) if (e.Ranges == null) return; - if (_model.IsStopped) + if (_model == null || _model.IsStopped) return; int firstChangedLineIndex = int.MaxValue; diff --git a/src/AvaloniaEdit.TextMate/TextTransformation.cs b/src/AvaloniaEdit.TextMate/TextTransformation.cs index ca11980d..bfe7dfd7 100644 --- a/src/AvaloniaEdit.TextMate/TextTransformation.cs +++ b/src/AvaloniaEdit.TextMate/TextTransformation.cs @@ -1,12 +1,9 @@ using System; -using System.Collections.Generic; using Avalonia.Media; using AvaloniaEdit.Document; -using TextMateSharp.Model; - namespace AvaloniaEdit.TextMate { public abstract class TextTransformation : TextSegment @@ -27,12 +24,15 @@ public interface IColorMap IBrush GetBrush(int color); } - int _foreground; - int _background; - int _fontStyle; + private IColorMap _colorMap; + private Action _exceptionHandler; + private int _foreground; + private int _background; + private int _fontStyle; public ForegroundTextTransformation( IColorMap colorMap, + Action exceptionHandler, int startOffset, int endOffset, int foreground, @@ -40,6 +40,7 @@ public ForegroundTextTransformation( int fontStyle) : base(startOffset, endOffset) { _colorMap = colorMap; + _exceptionHandler = exceptionHandler; _foreground = foreground; _background = background; _fontStyle = fontStyle; @@ -47,23 +48,25 @@ public ForegroundTextTransformation( public override void Transform(GenericLineTransformer transformer, DocumentLine line) { - if (Length == 0) + try { - return; - } + if (Length == 0) + { + return; + } - var formattedOffset = 0; - var endOffset = line.EndOffset; + var formattedOffset = 0; + var endOffset = line.EndOffset; - if (StartOffset > line.Offset) - { - formattedOffset = StartOffset - line.Offset; - } + if (StartOffset > line.Offset) + { + formattedOffset = StartOffset - line.Offset; + } - if (EndOffset < line.EndOffset) - { - endOffset = EndOffset; - } + if (EndOffset < line.EndOffset) + { + endOffset = EndOffset; + } transformer.SetTextStyle(line, formattedOffset, endOffset - line.Offset - formattedOffset, _colorMap.GetBrush(_foreground), @@ -71,6 +74,11 @@ public override void Transform(GenericLineTransformer transformer, DocumentLine GetFontStyle(), GetFontWeight(), IsUnderline()); + } + catch(Exception ex) + { + _exceptionHandler?.Invoke(ex); + } } FontStyle GetFontStyle() @@ -99,7 +107,5 @@ bool IsUnderline() return false; } - - IColorMap _colorMap; } } \ No newline at end of file