diff --git a/src/AddIns/BackendBindings/XamlBinding/XamlBinding.Tests/ExtensionsTests.cs b/src/AddIns/BackendBindings/XamlBinding/XamlBinding.Tests/ExtensionsTests.cs
new file mode 100644
index 0000000000..d960ace613
--- /dev/null
+++ b/src/AddIns/BackendBindings/XamlBinding/XamlBinding.Tests/ExtensionsTests.cs
@@ -0,0 +1,73 @@
+//
+//
+//
+//
+// $Revision$
+//
+
+
+using System;
+using NUnit.Framework;
+
+namespace ICSharpCode.XamlBinding.Tests
+{
+ [TestFixture]
+ public class ExtensionsTests
+ {
+ [Test]
+ public void StringReplaceTest1()
+ {
+ string text = "Hello World!";
+ int index = 0;
+ int length = 5;
+ string newText = "Bye";
+
+ string result = text.Replace(index, length, newText);
+ string expected = "Bye World!";
+
+ Assert.AreEqual(expected, result);
+ }
+
+ [Test]
+ public void StringReplaceTest2()
+ {
+ string text = "My Hello World!";
+ int index = 3;
+ int length = 5;
+ string newText = "Bye";
+
+ string result = text.Replace(index, length, newText);
+ string expected = "My Bye World!";
+
+ Assert.AreEqual(expected, result);
+ }
+
+ [Test]
+ public void StringReplaceTest3()
+ {
+ string text = "Hello World!";
+ int index = 6;
+ int length = 5;
+ string newText = "Byte";
+
+ string result = text.Replace(index, length, newText);
+ string expected = "Hello Byte!";
+
+ Assert.AreEqual(expected, result);
+ }
+
+ [Test]
+ public void StringReplaceTest4()
+ {
+ string text = "Hello World!";
+ int index = 11;
+ int length = 1;
+ string newText = "?";
+
+ string result = text.Replace(index, length, newText);
+ string expected = "Hello World?";
+
+ Assert.AreEqual(expected, result);
+ }
+ }
+}
diff --git a/src/AddIns/BackendBindings/XamlBinding/XamlBinding.Tests/ResolveContextTests.cs b/src/AddIns/BackendBindings/XamlBinding/XamlBinding.Tests/ResolveContextTests.cs
new file mode 100644
index 0000000000..c4772876ef
--- /dev/null
+++ b/src/AddIns/BackendBindings/XamlBinding/XamlBinding.Tests/ResolveContextTests.cs
@@ -0,0 +1,71 @@
+//
+//
+//
+//
+// $Revision$
+//
+
+using ICSharpCode.XmlEditor;
+using System;
+using NUnit.Framework;
+
+namespace ICSharpCode.XamlBinding.Tests
+{
+ [TestFixture]
+ public class ResolveContextTests
+ {
+ [Test]
+ public void ContextNoneDescriptionTest()
+ {
+ string xaml = "\n\t\n";
+ XamlContext context = CompletionDataHelper.ResolveContext(xaml, "", 2, 1);
+
+ Assert.AreEqual(XamlContextDescription.None, context.Description);
+ }
+
+ [Test]
+ public void ContextNoneDescriptionTest2()
+ {
+ string xaml = "\n\t\n";
+ XamlContext context = CompletionDataHelper.ResolveContext(xaml, "", 1, 7);
+
+ Assert.AreEqual(XamlContextDescription.None, context.Description);
+ }
+
+ [Test]
+ public void ContextNoneDescriptionTest3()
+ {
+ string xaml = "\n\t\n";
+ XamlContext context = CompletionDataHelper.ResolveContext(xaml, "", 3, 1);
+
+ Assert.AreEqual(XamlContextDescription.None, context.Description);
+ }
+
+ [Test]
+ public void ContextAtTagDescriptionTest()
+ {
+ string xaml = "\n\t\n";
+ XamlContext context = CompletionDataHelper.ResolveContext(xaml, "", 1, 2);
+
+ Assert.AreEqual(XamlContextDescription.AtTag, context.Description);
+ }
+
+ [Test]
+ public void ContextAtTagDescriptionTest2()
+ {
+ string xaml = "\n\t\n";
+ XamlContext context = CompletionDataHelper.ResolveContext(xaml, "", 2, 11);
+
+ Assert.AreEqual(XamlContextDescription.AtTag, context.Description);
+ }
+
+ [Test]
+ public void ContextInTagDescriptionTest()
+ {
+ string xaml = "\n\t\n";
+ XamlContext context = CompletionDataHelper.ResolveContext(xaml, "", 2, 26);
+
+ Assert.AreEqual(XamlContextDescription.InTag, context.Description);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/AddIns/BackendBindings/XamlBinding/XamlBinding.Tests/XamlBinding.Tests.csproj b/src/AddIns/BackendBindings/XamlBinding/XamlBinding.Tests/XamlBinding.Tests.csproj
index f23aade326..2b64693727 100644
--- a/src/AddIns/BackendBindings/XamlBinding/XamlBinding.Tests/XamlBinding.Tests.csproj
+++ b/src/AddIns/BackendBindings/XamlBinding/XamlBinding.Tests/XamlBinding.Tests.csproj
@@ -53,8 +53,10 @@
Properties\GlobalAssemblyInfo.cs
+
+
@@ -63,6 +65,7 @@
{924EE450-603D-49C1-A8E5-4AFAA31CE6F3}
ICSharpCode.SharpDevelop.Dom
+ False
{DCA2703D-250A-463E-A68A-07ED105AE6BD}
diff --git a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlColorizer.cs b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlColorizer.cs
index 1ed209f9d6..ccc364a196 100644
--- a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlColorizer.cs
+++ b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlColorizer.cs
@@ -6,8 +6,11 @@
//
using System;
-using System.Linq;
using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading;
+
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Rendering;
using ICSharpCode.SharpDevelop;
@@ -15,24 +18,135 @@ using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.XmlEditor;
-using System.Diagnostics;
+using System.Windows.Threading;
namespace ICSharpCode.XamlBinding
{
+ using Tasks = System.Threading.Tasks;
+
public class XamlColorizer : DocumentColorizingTransformer
{
static readonly XamlColorizerSettings defaultSettings = new XamlColorizerSettings();
+
+ public struct Highlight {
+ public IMember Member { get; set; }
+ public HighlightingInfo Info { get; set; }
+ }
+
+ public sealed class HighlightTask {
+ // input
+ public string FileContent { get; private set; }
+ public string FileName { get; private set; }
+ public string LineText { get; private set; }
+ public int LineNumber { get; private set; }
+ public int Offset { get; private set; }
+
+ TextView textView;
+
+ public HighlightTask(string fileContent, string fileName, DocumentLine line, TextView textView)
+ {
+ this.FileContent = fileContent;
+ this.FileName = fileName;
+ this.LineText = line.Text;
+ this.LineNumber = line.LineNumber;
+ this.Offset = line.Offset;
+ this.task = new System.Threading.Tasks.Task(Process);
+ this.textView = textView;
+ }
+
+ IList results;
+
+ // output
+ public IList GetResults()
+ {
+ return results;
+ }
+
+ public bool IsStillValid(DocumentLine line)
+ {
+ return this.Offset == line.Offset && this.LineText == line.Text;
+ }
+
+ Tasks.Task task;
+
+ public void Start()
+ {
+ task.Start();
+ }
+
+ public void Cancel()
+ {
+ if (task != null)
+ task.Cancel();
+ }
+
+ public bool IsCompleted {
+ get {
+ return task.IsCompleted;
+ }
+ }
+
+ void Process()
+ {
+ List results = new List();
+
+ foreach (HighlightingInfo info in GetInfo()) {
+ IMember member = null;
+
+ if (!info.Token.StartsWith("xmlns")) {
+ MemberResolveResult rr = new XamlResolver().Resolve(info.GetExpressionResult(), info.Context.ParseInformation, FileContent) as MemberResolveResult;
+ member = (rr != null) ? rr.ResolvedMember : null;
+ }
+
+ results.Add(new Highlight() { Member = member, Info = info });
+ }
+
+ this.results = results;
+
+ WorkbenchSingleton.SafeThreadAsyncCall(InvokeRedraw);
+ }
+
+ void InvokeRedraw()
+ {
+ textView.Redraw(this.Offset, this.LineText.Length, DispatcherPriority.Background);
+ }
+
+ IEnumerable GetInfo()
+ {
+ int index = -1;
+ int ltCharIndex = -1;
+ XamlContext context = null;
+ List infos = new List();
+
+ do {
+ index = LineText.IndexOf('=', index + 1);
+ if (index > -1) {
+ context = CompletionDataHelper.ResolveContext(FileContent, FileName, LineNumber, index + 1);
+ if (!string.IsNullOrEmpty(context.AttributeName)) {
+ int startIndex = LineText.Substring(0, index).LastIndexOf(context.AttributeName);
+ infos.Add(new HighlightingInfo(context.AttributeName, startIndex, startIndex + context.AttributeName.Length, Offset, context));
+ }
+ }
+ } while (index > -1);
+
+ return infos;
+ }
+ }
+
XamlColorizerSettings settings = defaultSettings;
string fileContent;
string fileName;
- ParseInformation parseInfo;
- XamlResolver resolver = new XamlResolver();
+
+ Dictionary highlightCache = new Dictionary();
public IViewContent Content { get; set; }
- public XamlColorizer(IViewContent content)
+ public AvalonEdit.Rendering.TextView TextView { get; set; }
+
+ public XamlColorizer(IViewContent content, TextView textView)
{
this.Content = content;
+ this.TextView = textView;
}
protected override void Colorize(ITextRunConstructionContext context)
@@ -42,7 +156,6 @@ namespace ICSharpCode.XamlBinding
if (document == null)
return;
- this.parseInfo = ParserService.GetParseInformation(Content.PrimaryFileName);
this.fileContent = document.GetDocumentForFile(this.Content.PrimaryFile).CreateSnapshot().Text;
this.fileName = this.Content.PrimaryFileName;
@@ -51,45 +164,37 @@ namespace ICSharpCode.XamlBinding
protected override void ColorizeLine(DocumentLine line)
{
- if (!line.IsDeleted) {
- HighlightingInfo[] infos = GetInfoForLine(line);
-
- foreach (HighlightingInfo info in infos) {
- MemberResolveResult rr = resolver.Resolve(info.GetExpressionResult(), parseInfo, fileContent) as MemberResolveResult;
- IMember member = (rr != null) ? rr.ResolvedMember : null;
-
- if (member != null) {
- if (member is IEvent)
- ChangeLinePart(line.Offset + info.StartOffset, line.Offset + info.EndOffset, HighlightEvent);
- else
- ChangeLinePart(line.Offset + info.StartOffset, line.Offset + info.EndOffset, HighlightProperty);
- } else {
- if (info.Token.StartsWith("xmlns"))
- ChangeLinePart(line.Offset + info.StartOffset, line.Offset + info.EndOffset, HighlightNamespaceDeclaration);
- }
+ if (line.IsDeleted)
+ return;
+
+ if (!highlightCache.ContainsKey(line.LineNumber)) {
+ HighlightTask task = new HighlightTask(this.fileContent, this.fileName, line, this.TextView);
+ task.Start();
+ highlightCache.Add(line.LineNumber, task);
+ } else {
+ HighlightTask task = highlightCache[line.LineNumber];
+ if (task.IsCompleted && task.IsStillValid(line)) {
+ task.GetResults().ForEach(result => ColorizeMember(result.Info, line, result.Member));
+ } else {
+ task.Cancel();
+ task = new HighlightTask(this.fileContent, this.fileName, line, this.TextView);
+ task.Start();
+ highlightCache[line.LineNumber] = task;
}
}
}
- HighlightingInfo[] GetInfoForLine(DocumentLine line)
+ void ColorizeMember(HighlightingInfo info, DocumentLine line, IMember member)
{
- int index = -1;
- int ltCharIndex = -1;
- XamlContext context = null;
- List infos = new List();
-
- do {
- index = line.Text.IndexOf('=', index + 1);
- if (index > -1) {
- context = CompletionDataHelper.ResolveContext(this.fileContent, this.fileName, line.LineNumber, index + 1);
- if (!string.IsNullOrEmpty(context.AttributeName)) {
- int startIndex = line.Text.Substring(0, index).LastIndexOf(context.AttributeName);
- infos.Add(new HighlightingInfo(context.AttributeName, startIndex, startIndex + context.AttributeName.Length, line.Offset, context));
- }
- }
- } while (index > -1);
-
- return infos.ToArray();
+ if (member != null) {
+ if (member is IEvent)
+ ChangeLinePart(line.Offset + info.StartOffset, line.Offset + info.EndOffset, HighlightEvent);
+ else
+ ChangeLinePart(line.Offset + info.StartOffset, line.Offset + info.EndOffset, HighlightProperty);
+ } else {
+ if (info.Token.StartsWith("xmlns"))
+ ChangeLinePart(line.Offset + info.StartOffset, line.Offset + info.EndOffset, HighlightNamespaceDeclaration);
+ }
}
void HighlightProperty(VisualLineElement element)
@@ -110,7 +215,7 @@ namespace ICSharpCode.XamlBinding
element.TextRunProperties.SetBackgroundBrush(settings.NamespaceDeclarationBackgroundBrush);
}
- struct HighlightingInfo
+ public struct HighlightingInfo
{
public static readonly HighlightingInfo Empty = new HighlightingInfo(string.Empty, 0, 0, 0, new XamlContext());
@@ -154,4 +259,4 @@ namespace ICSharpCode.XamlBinding
}
}
}
-}
+}
\ No newline at end of file
diff --git a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlColorizerServer.cs b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlColorizerServer.cs
index 4cb6b4a8b0..e2c3c12591 100644
--- a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlColorizerServer.cs
+++ b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlColorizerServer.cs
@@ -5,6 +5,7 @@
// $Revision$
//
+using ICSharpCode.XmlEditor;
using System;
using System.IO;
using ICSharpCode.AvalonEdit.Rendering;
@@ -32,9 +33,10 @@ namespace ICSharpCode.XamlBinding
ITextEditorProvider textEditor = e.Content as ITextEditorProvider;
if (textEditor != null) {
TextView textView = textEditor.TextEditor.GetService(typeof(TextView)) as TextView;
+
if (textView != null)
- textView.LineTransformers.Add(new XamlColorizer(e.Content));
+ textView.LineTransformers.Add(new XamlColorizer(e.Content, textView));
}
}
}
-}
+}
\ No newline at end of file
diff --git a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlResolver.cs b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlResolver.cs
index e2172fe9fd..9428c59940 100644
--- a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlResolver.cs
+++ b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlResolver.cs
@@ -235,7 +235,7 @@ namespace ICSharpCode.XamlBinding
{
if (propertyOrEvent == null)
return null;
- if (propertyOrEvent is IEvent) {
+ if (propertyOrEvent is IEvent && callingClass != null) {
return new MethodGroupResolveResult(callingClass, null, callingClass.DefaultReturnType, expression);
}