Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/monodevelop.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGreg Munn <greg@sgmunn.com>2018-04-12 18:46:27 +0300
committerGitHub <noreply@github.com>2018-04-12 18:46:27 +0300
commit5af3e98549653fcc5335896ccc296343d08f31bb (patch)
tree2742ed6ea967410ce224e594b7a6269e54a2fb81
parentd2c212a04a47c3176572edcc85319459646f9e19 (diff)
parent5393a5a7cce3c4d9697aefd7951850eff601eda1 (diff)
Merge pull request #4488 from mono/d15-6-fix592988monodevelop-7.4.3.10
D15 6 fix592988
-rw-r--r--main/src/addins/MonoDevelop.SourceEditor2/Mono.TextEditor/Gui/TextViewMargin.SpanUpdateListener.cs123
-rw-r--r--main/src/addins/MonoDevelop.SourceEditor2/Mono.TextEditor/Gui/TextViewMargin.cs37
-rw-r--r--main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.csproj1
-rw-r--r--main/src/core/MonoDevelop.TextEditor.Tests/Mono.TextEditor.Tests/TextViewTests.cs139
-rw-r--r--main/src/core/MonoDevelop.TextEditor.Tests/MonoDevelop.TextEditor.Tests.csproj1
5 files changed, 282 insertions, 19 deletions
diff --git a/main/src/addins/MonoDevelop.SourceEditor2/Mono.TextEditor/Gui/TextViewMargin.SpanUpdateListener.cs b/main/src/addins/MonoDevelop.SourceEditor2/Mono.TextEditor/Gui/TextViewMargin.SpanUpdateListener.cs
new file mode 100644
index 0000000000..f0700ee6ee
--- /dev/null
+++ b/main/src/addins/MonoDevelop.SourceEditor2/Mono.TextEditor/Gui/TextViewMargin.SpanUpdateListener.cs
@@ -0,0 +1,123 @@
+//
+// TextViewMargin.SpanUpdateListener.cs
+//
+// Author:
+// Mike Krüger <mikkrg@microsoft.com>
+//
+// Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Linq;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.InteropServices;
+
+using Mono.TextEditor.Highlighting;
+
+using MonoDevelop.Components.AtkCocoaHelper;
+
+using Gdk;
+using Gtk;
+using System.Timers;
+using System.Diagnostics;
+using MonoDevelop.Components;
+using MonoDevelop.Core;
+using MonoDevelop.Core.Text;
+using MonoDevelop.Ide.Editor;
+using MonoDevelop.Ide.Editor.Highlighting;
+using System.Collections.Immutable;
+using System.Threading;
+using MonoDevelop.Ide;
+using System.Threading.Tasks;
+
+namespace Mono.TextEditor
+{
+ partial class TextViewMargin
+ {
+ internal class SpanUpdateListener : IDisposable
+ {
+ readonly MonoTextEditor textEditor;
+
+ public bool HasUpdatedMultilineSpan { get; set; }
+
+ public SpanUpdateListener (MonoTextEditor textEditor)
+ {
+ this.textEditor = textEditor;
+ textEditor.Document.TextChanged += Document_TextChanged;
+ textEditor.Document.TextChanging += Document_TextChanging;
+ }
+
+ public void Dispose()
+ {
+ textEditor.Document.TextChanged -= Document_TextChanged;
+ textEditor.Document.TextChanging -= Document_TextChanging;
+ }
+
+ List<HighlightedLine> lines = new List<HighlightedLine> ();
+
+ void Document_TextChanging (object sender, TextChangeEventArgs e)
+ {
+ HasUpdatedMultilineSpan = false;
+ foreach (var change in e.TextChanges) {
+ var layout = textEditor.TextViewMargin.GetLayout (textEditor.GetLineByOffset (change.Offset));
+ lines.Add (layout.HighlightedLine);
+ }
+ }
+
+ void Document_TextChanged (object sender, TextChangeEventArgs e)
+ {
+ int i = 0;
+
+ foreach (var change in e.TextChanges) {
+ if (i >= lines.Count)
+ break; // should never happen
+ var oldHighlightedLine = lines [i++];
+ var curLine = textEditor.GetLineByOffset (change.Offset);
+ var curLayout = textEditor.TextViewMargin.GetLayout (curLine);
+ if (!UpdateLineHighlight (curLine.LineNumber, oldHighlightedLine, curLayout.HighlightedLine))
+ break;
+ }
+ lines.Clear ();
+ }
+
+ bool UpdateLineHighlight (int lineNumber, HighlightedLine oldLine, HighlightedLine newLine)
+ {
+ if (oldLine != null && ShouldUpdateSpan (oldLine, newLine)) {
+ textEditor.TextViewMargin.PurgeLayoutCacheAfter (lineNumber);
+ textEditor.QueueDraw ();
+ HasUpdatedMultilineSpan = true;
+ return false;
+ }
+ return true;
+ }
+
+ static bool ShouldUpdateSpan (HighlightedLine line1, HighlightedLine line2)
+ {
+ if (line1.IsContinuedBeyondLineEnd != line2.IsContinuedBeyondLineEnd)
+ return true;
+ if (line1.IsContinuedBeyondLineEnd == true) {
+ return line1.Segments.Last ().ScopeStack.Peek () != line2.Segments.Last ().ScopeStack.Peek ();
+ }
+ return false;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/main/src/addins/MonoDevelop.SourceEditor2/Mono.TextEditor/Gui/TextViewMargin.cs b/main/src/addins/MonoDevelop.SourceEditor2/Mono.TextEditor/Gui/TextViewMargin.cs
index e6de21a47a..ea3ffd4c20 100644
--- a/main/src/addins/MonoDevelop.SourceEditor2/Mono.TextEditor/Gui/TextViewMargin.cs
+++ b/main/src/addins/MonoDevelop.SourceEditor2/Mono.TextEditor/Gui/TextViewMargin.cs
@@ -35,7 +35,7 @@ using Mono.TextEditor.Highlighting;
using MonoDevelop.Components.AtkCocoaHelper;
-using Gdk;
+using Gdk;
using Gtk;
using System.Timers;
using System.Diagnostics;
@@ -51,7 +51,7 @@ using System.Threading.Tasks;
namespace Mono.TextEditor
{
- class TextViewMargin : Margin
+ partial class TextViewMargin : Margin
{
readonly MonoTextEditor textEditor;
Pango.TabArray tabArray;
@@ -62,6 +62,9 @@ namespace Mono.TextEditor
internal double charWidth;
bool isMonospacedFont;
+ SpanUpdateListener spanUpdateListener;
+
+ internal SpanUpdateListener SpanUpdater { get => spanUpdateListener; }
double LineHeight {
get {
@@ -290,7 +293,7 @@ namespace Mono.TextEditor
accessible.Margin = this;
this.textEditor = textEditor;
-
+ spanUpdateListener = new SpanUpdateListener (textEditor);
textEditor.Document.TextChanged += HandleTextReplaced;
textEditor.HighlightSearchPatternChanged += TextEditor_HighlightSearchPatternChanged;
textEditor.GetTextEditorData ().SearchChanged += HandleSearchChanged;
@@ -716,7 +719,10 @@ namespace Mono.TextEditor
marker.Dispose ();
eolMarkerLayout = null;
}
-
+ if (spanUpdateListener != null) {
+ spanUpdateListener.Dispose ();
+ spanUpdateListener = null;
+ }
DisposeLayoutDict ();
if (tabArray != null)
tabArray.Dispose ();
@@ -1065,7 +1071,7 @@ namespace Mono.TextEditor
continue;
chunkMarker.TransformChunks (chunks);
}
-
+ wrapper.HighlightedLine = cachedChunks.Item3;
wrapper.Chunks = chunks;
foreach (var chunk in chunks) {
try {
@@ -1354,35 +1360,26 @@ namespace Mono.TextEditor
}
}
CancellationTokenSource cacheSrc = new CancellationTokenSource ();
- Tuple<List<ColoredSegment>, bool> GetCachedChunks (TextDocument doc, DocumentLine line, int offset, int length)
+ Tuple<List<ColoredSegment>, bool, HighlightedLine> GetCachedChunks (TextDocument doc, DocumentLine line, int offset, int length)
{
var lineNumber = line.LineNumber;
var token = cacheSrc.Token;
var task = doc.SyntaxMode.GetHighlightedLineAsync (line, token);
if (task.IsCompleted) {
if (task.Result != null) {
- return Tuple.Create (TrimChunks (task.Result.Segments, offset - line.Offset, length), true);
+ return Tuple.Create (TrimChunks (task.Result.Segments, offset - line.Offset, length), true, task.Result);
}
}
try {
var taskResult = task.WaitAndGetResult (default (CancellationToken));
- return Tuple.Create (TrimChunks (taskResult.Segments, offset - line.Offset, length), true);
+ return Tuple.Create (TrimChunks (taskResult.Segments, offset - line.Offset, length), true, taskResult);
} catch (Exception e) {
LoggingService.LogError ("Error while highlighting", e);
- return Tuple.Create (new List<ColoredSegment> (new [] { new ColoredSegment (0, line.Length, ScopeStack.Empty) }), false);
- }
- }
-
- static bool ShouldUpdateSpan (HighlightedLine line1, HighlightedLine line2)
- {
- if (line1.IsContinuedBeyondLineEnd != line2.IsContinuedBeyondLineEnd)
- return true;
- if (line1.IsContinuedBeyondLineEnd == true) {
- return line1.Segments.Last ().ScopeStack.Peek () != line2.Segments.Last ().ScopeStack.Peek ();
+ return Tuple.Create (new List<ColoredSegment> (new [] { new ColoredSegment (0, line.Length, ScopeStack.Empty) }), false, (HighlightedLine)null);
}
- return false;
}
+
internal static List<ColoredSegment> TrimChunks (IReadOnlyList<ColoredSegment> segments, int offset, int length)
{
var result = new List<ColoredSegment> ();
@@ -1536,6 +1533,8 @@ namespace Mono.TextEditor
set;
}
+ internal HighlightedLine HighlightedLine { get; set; }
+
public string Text {
get {
return Layout.Text;
diff --git a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.csproj b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.csproj
index 4a411f46ec..17e95a1ff6 100644
--- a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.csproj
+++ b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.csproj
@@ -286,6 +286,7 @@
<Compile Include="MonoDevelop.SourceEditor\TextMarker\LineSeparatorMarker.cs" />
<Compile Include="MonoDevelop.SourceEditor.QuickTasks\QuickTaskOverviewMode.IndicatorDrawingCache.cs" />
<Compile Include="MonoDevelop.SourceEditor.QuickTasks\QuickTaskOverviewMode.IdleUpdater.cs" />
+ <Compile Include="Mono.TextEditor\Gui\TextViewMargin.SpanUpdateListener.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="gtk-gui\gui.stetic">
diff --git a/main/src/core/MonoDevelop.TextEditor.Tests/Mono.TextEditor.Tests/TextViewTests.cs b/main/src/core/MonoDevelop.TextEditor.Tests/Mono.TextEditor.Tests/TextViewTests.cs
new file mode 100644
index 0000000000..8c953d9c54
--- /dev/null
+++ b/main/src/core/MonoDevelop.TextEditor.Tests/Mono.TextEditor.Tests/TextViewTests.cs
@@ -0,0 +1,139 @@
+//
+// TextViewTests.cs
+//
+// Author:
+// Mike Krüger <mikkrg@microsoft.com>
+//
+// Copyright (c) 2018 Microsoft Corporation. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System.IO;
+using System.Text;
+using System.Linq;
+using NUnit.Framework;
+using Mono.TextEditor.Utils;
+using System.Reflection;
+using MonoDevelop.Core.Text;
+using MonoDevelop.Ide.Editor.Highlighting;
+using MonoDevelop.Ide.Editor;
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Collections.Generic;
+
+namespace Mono.TextEditor.Tests
+{
+ [TestFixture]
+ public class TextViewTests
+ {
+ class TestSyntaxMode : ISyntaxHighlighting
+ {
+ public event EventHandler<MonoDevelop.Ide.Editor.LineEventArgs> HighlightingStateChanged;
+
+ public void Dispose ()
+ {
+ }
+
+ public Task<HighlightedLine> GetHighlightedLineAsync (IDocumentLine line, CancellationToken cancellationToken)
+ {
+ var segments = new List<ColoredSegment> ();
+ for (int i = 0; i < line.Length;i++){
+ if (i > 0 && i == line.Length - 1) {
+ segments.Add (new ColoredSegment (i, 2, ScopeStack.Empty));
+ break;
+ }
+ segments.Add (new ColoredSegment (i, 1, ScopeStack.Empty));
+ }
+
+ return Task.FromResult (new HighlightedLine (line, segments));
+ }
+
+ public Task<ScopeStack> GetScopeStackAsync (int offset, CancellationToken cancellationToken)
+ {
+ return Task.FromResult (ScopeStack.Empty);
+ }
+ }
+
+ [Test]
+ public void TestFirstTimeUpdate ()
+ {
+ var editor = new MonoTextEditor ();
+ editor.GetTextEditorData ().Document.SyntaxMode = new TestSyntaxMode ();
+ editor.Text = @"1
+2
+3
+4
+5";
+ editor.Caret.Location = new DocumentLocation (2, 1);
+ editor.InsertAtCaret ("a");
+ Assert.IsTrue (editor.TextViewMargin.SpanUpdater.HasUpdatedMultilineSpan);
+ }
+
+ [Test]
+ public void TestSubsequentUpdate ()
+ {
+ var editor = new MonoTextEditor ();
+ editor.GetTextEditorData ().Document.SyntaxMode = new TestSyntaxMode ();
+ editor.Text = @"1
+2
+3
+4
+5";
+ editor.Caret.Location = new DocumentLocation (2, 1);
+ editor.InsertAtCaret ("a");
+ Assert.IsTrue (editor.TextViewMargin.SpanUpdater.HasUpdatedMultilineSpan);
+ editor.InsertAtCaret ("a");
+ Assert.IsFalse (editor.TextViewMargin.SpanUpdater.HasUpdatedMultilineSpan);
+ }
+
+ [Test]
+ public void TestBackspace ()
+ {
+ var editor = new MonoTextEditor ();
+ editor.GetTextEditorData ().Document.SyntaxMode = new TestSyntaxMode ();
+ editor.Text = @"1
+2
+3
+4
+5";
+ editor.Caret.Location = new DocumentLocation (2, 1);
+ editor.InsertAtCaret ("a");
+ Assert.IsTrue (editor.TextViewMargin.SpanUpdater.HasUpdatedMultilineSpan);
+ DeleteActions.Backspace (editor.GetTextEditorData ());
+ Assert.IsTrue (editor.TextViewMargin.SpanUpdater.HasUpdatedMultilineSpan);
+ }
+
+ [Test]
+ public void TestDeleteNoUpdate ()
+ {
+ var editor = new MonoTextEditor ();
+ editor.GetTextEditorData ().Document.SyntaxMode = new TestSyntaxMode ();
+ editor.Text = @"1
+2
+3
+4
+5";
+ editor.Caret.Location = new DocumentLocation (2, 1);
+ DeleteActions.Delete (editor.GetTextEditorData ());
+ Assert.IsFalse (editor.TextViewMargin.SpanUpdater.HasUpdatedMultilineSpan);
+ }
+
+ }
+} \ No newline at end of file
diff --git a/main/src/core/MonoDevelop.TextEditor.Tests/MonoDevelop.TextEditor.Tests.csproj b/main/src/core/MonoDevelop.TextEditor.Tests/MonoDevelop.TextEditor.Tests.csproj
index 2e81e3c00d..aff4067d1a 100644
--- a/main/src/core/MonoDevelop.TextEditor.Tests/MonoDevelop.TextEditor.Tests.csproj
+++ b/main/src/core/MonoDevelop.TextEditor.Tests/MonoDevelop.TextEditor.Tests.csproj
@@ -81,6 +81,7 @@
<Compile Include="Mono.TextEditor.Tests\TextEditorDataTests.cs" />
<Compile Include="MonoDevelop.TextEditor.Extension\NavigationExtensionTests.cs" />
<Compile Include="Mono.TextEditor.Tests\DiffTrackerTests.cs" />
+ <Compile Include="Mono.TextEditor.Tests\TextViewTests.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>