From b5a82b5fb052736f5674caf80683463cefa88f71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20Kr=C3=BCger?= Date: Thu, 8 Aug 2019 11:30:20 +0200 Subject: Fixes VSTS Bug 959146: System.NullReferenceException exception in Mono.TextEditor.Utils.TextBreaker.BreakLinesIntoWords() https://devdiv.visualstudio.com/DevDiv/_workitems/edit/959146 I can't find the cause of it. I checked the parameters of BreakLinesIntoWords now. The diff must be out of sync with the text document that should now not happen, it's checked before paint that the versions match. In any case that implementation is more solid. --- .../EditorCompareWidgetBase.cs | 41 ++++++++++++++++++++-- .../Mono.TextEditor.Utils/TextBreaker.cs | 9 +++++ 2 files changed, 48 insertions(+), 2 deletions(-) (limited to 'main') diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/EditorCompareWidgetBase.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/EditorCompareWidgetBase.cs index df71cb3487..1f10044251 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/EditorCompareWidgetBase.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/EditorCompareWidgetBase.cs @@ -40,6 +40,7 @@ using MonoDevelop.Projects.Text; using MonoDevelop.Core.Text; using MonoDevelop.Ide.Editor; using Microsoft.VisualStudio.Text; +using MonoDevelop.Ide.TextEditing; namespace MonoDevelop.VersionControl.Views { @@ -68,6 +69,7 @@ namespace MonoDevelop.VersionControl.Views set { leftDiff = value; OnDiffChanged (EventArgs.Empty); + SetDiffEditorVersions (); } } @@ -77,9 +79,32 @@ namespace MonoDevelop.VersionControl.Views set { rightDiff = value; OnDiffChanged (EventArgs.Empty); + SetDiffEditorVersions (); } } - + + ITextSourceVersion [] diffVersions; + + void SetDiffEditorVersions () + { + if (diffVersions == null) // editors.Length never changes + diffVersions = new ITextSourceVersion [editors.Length]; + for (int i = 0; i < editors.Length; i++) { + diffVersions [i] = editors [i].Document.Version; + } + } + + bool IsEditorDiffValid () + { + if (diffVersions == null) + return false; + for (int i = 0; i < editors.Length; i++) { + if (diffVersions [i].CompareAge (editors [i].Document.Version) != 0) + return false; + } + return true; + } + internal abstract MonoTextEditor MainEditor { get; } @@ -147,11 +172,15 @@ namespace MonoDevelop.VersionControl.Views if (editors.Length == 2) { editors[0].Painted += delegate (object sender, PaintEventArgs args) { + if (!IsEditorDiffValid ()) + return; var myEditor = (TextArea)sender; PaintEditorOverlay (myEditor, args, LeftDiff, true); }; editors[1].Painted += delegate (object sender, PaintEventArgs args) { + if (!IsEditorDiffValid ()) + return; var myEditor = (TextArea)sender; PaintEditorOverlay (myEditor, args, LeftDiff, false); }; @@ -160,15 +189,21 @@ namespace MonoDevelop.VersionControl.Views Add (rightDiffScrollBar); } else { editors[0].Painted += delegate (object sender, PaintEventArgs args) { + if (!IsEditorDiffValid ()) + return; var myEditor = (TextArea)sender; PaintEditorOverlay (myEditor, args, LeftDiff, true); }; editors[1].Painted += delegate (object sender, PaintEventArgs args) { + if (!IsEditorDiffValid ()) + return; var myEditor = (TextArea)sender; PaintEditorOverlay (myEditor, args, LeftDiff, false); PaintEditorOverlay (myEditor, args, RightDiff, false); }; editors[2].Painted += delegate (object sender, PaintEventArgs args) { + if (!IsEditorDiffValid ()) + return; var myEditor = (TextArea)sender; PaintEditorOverlay (myEditor, args, RightDiff, true); }; @@ -287,7 +322,9 @@ namespace MonoDevelop.VersionControl.Views static List BreakTextInWords (MonoTextEditor editor, int start, int count) { - return TextBreaker.BreakLinesIntoWords(editor, start, count); + var s = Math.Min (start, editor.LineCount); + var c = Math.Min (count, editor.LineCount - (s - 1)); + return TextBreaker.BreakLinesIntoWords(editor, s, c); } static List CalculateChunkPath (MonoTextEditor editor, List diff, List words, bool useRemove) diff --git a/main/src/core/Mono.TextEditor.Shared/Mono.TextEditor.Utils/TextBreaker.cs b/main/src/core/Mono.TextEditor.Shared/Mono.TextEditor.Utils/TextBreaker.cs index 5be96e1b53..a727db5439 100644 --- a/main/src/core/Mono.TextEditor.Shared/Mono.TextEditor.Utils/TextBreaker.cs +++ b/main/src/core/Mono.TextEditor.Shared/Mono.TextEditor.Utils/TextBreaker.cs @@ -25,6 +25,7 @@ // THE SOFTWARE. using System; using System.Collections.Generic; +using MonoDevelop.Core; using MonoDevelop.Core.Text; namespace Mono.TextEditor.Utils @@ -74,9 +75,17 @@ namespace Mono.TextEditor.Utils /// public static List BreakLinesIntoWords (TextDocument document, int startLine, int lineCount, bool includeDelimiter = true) { + if (document is null) + throw new ArgumentNullException (nameof (document)); + if (startLine < 1) + throw new ArgumentOutOfRangeException (nameof (startLine), "startLine >= 1, was " + startLine); + if (startLine - 1 + lineCount > document.LineCount) + throw new ArgumentOutOfRangeException (nameof (startLine), "startLine + lineCount <= " + (document.LineCount + 1) + ", was " + startLine); var result = new List (); for (int line = startLine; line < startLine + lineCount; line++) { var lineSegment = document.GetLine (line); + if (lineSegment == null) + continue; int offset = lineSegment.Offset; bool wasIdentifierPart = false; int lastWordEnd = 0; -- cgit v1.2.3