Browse Source

XamlBinding:

- fixed bug in XmlParser
- added Unit Tests
- implemented highlighting of ignored attributes

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@4497 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Siegfried Pammer 17 years ago
parent
commit
88d6f02ff2
  1. 19
      src/AddIns/BackendBindings/XamlBinding/XamlBinding.Tests/ResolveContextTests.cs
  2. 4
      src/AddIns/BackendBindings/XamlBinding/XamlBinding.Tests/Test2.xaml
  3. 54
      src/AddIns/BackendBindings/XamlBinding/XamlBinding.Tests/XmlTests.cs
  4. 72
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/CompletionDataHelper.cs
  5. 3
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/QualifiedNameWithLocation.cs
  6. 32
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/Utils.cs
  7. 35
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlCodeCompletionBinding.cs
  8. 92
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlColorizer.cs
  9. 6
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlColorizerSettings.cs
  10. 4
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlContext.cs
  11. 2
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlResolver.cs
  12. 9
      src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlParser.cs

19
src/AddIns/BackendBindings/XamlBinding/XamlBinding.Tests/ResolveContextTests.cs

@ -69,6 +69,15 @@ namespace ICSharpCode.XamlBinding.Tests @@ -69,6 +69,15 @@ namespace ICSharpCode.XamlBinding.Tests
Assert.AreEqual(XamlContextDescription.InTag, context.Description);
}
[Test]
public void ElementNameWithDotTest1()
{
string xaml = "<Grid>\n\t<Grid.ColumnDefinitions />\n</Grid>";
XamlContext context = CompletionDataHelper.ResolveContext(xaml, "", 2, 12);
Assert.AreEqual("Grid.ColumnDefinitions", context.ActiveElement.Name);
}
[Test]
public void ContextAtTagDescriptionTest3()
{
@ -107,5 +116,15 @@ namespace ICSharpCode.XamlBinding.Tests @@ -107,5 +116,15 @@ namespace ICSharpCode.XamlBinding.Tests
Assert.AreEqual("Window", context.ActiveElement.Name);
Assert.AreEqual(null, context.ParentElement);
}
[Test]
public void IgnoredXmlnsTest1()
{
string xaml = File.ReadAllText("Test2.xaml");
XamlContext context = CompletionDataHelper.ResolveContext(xaml, "", 11, 24);
Assert.AreEqual(1, context.IgnoredXmlns.Count);
Assert.AreEqual("d", context.IgnoredXmlns[0]);
}
}
}

4
src/AddIns/BackendBindings/XamlBinding/XamlBinding.Tests/Test2.xaml

@ -3,8 +3,10 @@ @@ -3,8 +3,10 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="XamlTest" Height="300" Width="300"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d"
>
<Grid>
<CheckBox xmlns:y="clr-namespace:ICSharpCode.Profiler.Controls;assembly=ICSharpCode.Profiler.Controls" />
<CheckBox d:Something="" />
</Grid>
</Window>

54
src/AddIns/BackendBindings/XamlBinding/XamlBinding.Tests/XmlTests.cs

@ -80,5 +80,59 @@ namespace ICSharpCode.XamlBinding.Tests @@ -80,5 +80,59 @@ namespace ICSharpCode.XamlBinding.Tests
Assert.AreEqual("{Binding Value, Path=Control}", XmlParser.GetAttributeValueAtIndex(xaml, offset));
Assert.AreEqual("val1", XmlParser.GetAttributeNameAtIndex(xaml, offset));
}
[Test]
public void AtEqualSignTest1()
{
string xaml = "<Test val1 = \"{Binding Value, Path=Control}\" />";
int offset = "<Test val1 =".Length;
Assert.AreEqual("val1", XmlParser.GetAttributeNameAtIndex(xaml, offset));
}
[Test]
public void AtEqualSignTest2()
{
string xaml = "<Test val1 = \"{Binding Value, Path=Control}\" />";
int offset = "<Te".Length;
Assert.AreEqual("", XmlParser.GetAttributeNameAtIndex(xaml, offset));
}
[Test]
public void AtEqualSignTest3()
{
string xaml = "<Test val1 = \"{Binding Value, Path=Control}\" />";
int offset = "<Test val1 = \"{Binding Value, Path".Length;
Assert.AreEqual("val1", XmlParser.GetAttributeNameAtIndex(xaml, offset));
}
[Test]
public void AtEqualSignTest4()
{
string xaml = "<Test val1 = \"{Binding Value, Path=Control}\" />";
int offset = "<Test val1 ".Length;
Assert.AreEqual("val1", XmlParser.GetAttributeNameAtIndex(xaml, offset));
}
[Test]
public void AtEqualSignTest5()
{
string xaml = "<Test val1 = \"{Binding Value, Path=Control}\" />";
int offset = "<Test val1 = \"{Binding Value, Path=".Length;
Assert.AreEqual("val1", XmlParser.GetAttributeNameAtIndex(xaml, offset));
}
[Test]
public void AtEqualSignTest6()
{
string xaml = "<Test val1 = \"{Binding Value, Path=Control}\" />";
int offset = "<Test val1 = \"{Binding Value, Path=C".Length;
Assert.AreEqual("val1", XmlParser.GetAttributeNameAtIndex(xaml, offset));
}
}
}

72
src/AddIns/BackendBindings/XamlBinding/XamlBinding/CompletionDataHelper.cs

@ -74,11 +74,12 @@ namespace ICSharpCode.XamlBinding @@ -74,11 +74,12 @@ namespace ICSharpCode.XamlBinding
XamlContextDescription description = XamlContextDescription.None;
Dictionary<string, string> xmlnsDefs;
List<string> ignoredXmlns;
QualifiedNameWithLocation active, parent;
int elementStartIndex;
bool isRoot;
Utils.LookUpInfoAtTarget(text, line, col, offset, out xmlnsDefs, out active, out parent, out elementStartIndex, out isRoot);
Utils.LookUpInfoAtTarget(text, line, col, offset, out xmlnsDefs, out ignoredXmlns, out active, out parent, out elementStartIndex, out isRoot);
string wordBeforeIndex = text.GetWordBeforeOffset(offset);
@ -103,17 +104,33 @@ namespace ICSharpCode.XamlBinding @@ -103,17 +104,33 @@ namespace ICSharpCode.XamlBinding
if (Utils.IsInsideXmlComment(text, offset))
description = XamlContextDescription.InComment;
int prefixEnd = attribute.IndexOf(':');
string prefix = "";
string xmlNamespace = "";
string localName = attribute;
if (prefixEnd > -1) {
prefix = attribute.Substring(0, prefixEnd);
localName = attribute.Substring(prefixEnd + 1, attribute.Length - prefix.Length - 1);
}
xmlnsDefs.TryGetValue(prefix, out xmlNamespace);
var qAttribute = new QualifiedNameWithLocation(localName, xmlNamespace, prefix, -1, -1);
var context = new XamlContext() {
Description = description,
ActiveElement = active,
ParentElement = parent,
AttributeName = attribute,
AttributeName = string.IsNullOrEmpty(attribute) ? null : qAttribute,
InRoot = isRoot,
AttributeValue = value,
RawAttributeValue = attributeValue,
ValueStartOffset = offsetFromValueStart,
XmlnsDefinitions = xmlnsDefs,
ParseInformation = info
ParseInformation = info,
IgnoredXmlns = ignoredXmlns
};
return context;
@ -272,7 +289,7 @@ namespace ICSharpCode.XamlBinding @@ -272,7 +289,7 @@ namespace ICSharpCode.XamlBinding
return string.Empty;
}
public static IList<ICompletionItem> CreateElementList(XamlCompletionContext context, bool classesOnly)
public static IList<ICompletionItem> CreateElementList(XamlCompletionContext context, bool classesOnly, bool includeAbstract)
{
var items = GetClassesFromContext(context);
var result = new List<ICompletionItem>();
@ -320,15 +337,24 @@ namespace ICSharpCode.XamlBinding @@ -320,15 +337,24 @@ namespace ICSharpCode.XamlBinding
foreach (var ns in items) {
foreach (var c in ns.Value) {
if (!(c.ClassType == ClassType.Class && !c.IsAbstract && !c.IsStatic &&
!c.DerivesFrom("System.Attribute") &&
c.Methods.Any(m => m.IsConstructor && m.IsPublic)))
continue;
if (includeAbstract) {
if (c.ClassType == ClassType.Class) {
if (!(!c.IsStatic && !c.DerivesFrom("System.Attribute") && c.Methods.Any(m => m.IsConstructor && m.IsPublic)))
continue;
} else if (c.ClassType == ClassType.Interface) {
} else {
continue;
}
} else {
if (!(c.ClassType == ClassType.Class && c.IsAbstract == includeAbstract && !c.IsStatic &&
!c.DerivesFrom("System.Attribute") && c.Methods.Any(m => m.IsConstructor && m.IsPublic)))
continue;
}
if (last != null && isList) {
var possibleTypes = rt.GetMethods()
.Where(a => a.Parameters.Count == 1 && a.Name == "Add")
.Select(method => method.Parameters.First().ReturnType.GetUnderlyingClass());
.Select(method => method.Parameters.First().ReturnType.GetUnderlyingClass()).Where(p => p != null);
if (!possibleTypes.Any(t => c.ClassInheritanceTreeClassesOnly.Any(c2 => c2.FullyQualifiedName == t.FullyQualifiedName)))
continue;
@ -365,7 +391,7 @@ namespace ICSharpCode.XamlBinding @@ -365,7 +391,7 @@ namespace ICSharpCode.XamlBinding
public static IEnumerable<ICompletionItem> CreateListOfMarkupExtensions(XamlCompletionContext context)
{
var list = CreateElementList(context, true);
var list = CreateElementList(context, true, false);
var neededItems = list.OfType<XamlCodeCompletionItem>()
.Where(i => (i.Entity as IClass).DerivesFrom("System.Windows.Markup.MarkupExtension"));
@ -394,7 +420,7 @@ namespace ICSharpCode.XamlBinding @@ -394,7 +420,7 @@ namespace ICSharpCode.XamlBinding
case XamlContextDescription.None:
if (context.Forced) {
list.Items.AddRange(standardElements);
list.Items.AddRange(CreateElementList(context, false));
list.Items.AddRange(CreateElementList(context, false, false));
AddClosingTagCompletion(context, list);
}
break;
@ -403,7 +429,7 @@ namespace ICSharpCode.XamlBinding @@ -403,7 +429,7 @@ namespace ICSharpCode.XamlBinding
list.Items.AddRange(CreateAttributeList(context, false));
} else {
list.Items.AddRange(standardElements);
list.Items.AddRange(CreateElementList(context, false));
list.Items.AddRange(CreateElementList(context, false, false));
AddClosingTagCompletion(context, list);
}
break;
@ -445,18 +471,17 @@ namespace ICSharpCode.XamlBinding @@ -445,18 +471,17 @@ namespace ICSharpCode.XamlBinding
{
if (context.ParentElement != null && !context.InRoot) {
ResolveResult rr = XamlResolver.Resolve(context.ParentElement.FullXmlName, context);
TypeResolveResult prr = XamlResolver.Resolve(context.ParentElement.FullXmlName.Substring(0, context.ParentElement.FullXmlName.IndexOf('.') + 1).TrimEnd('.'),
context) as TypeResolveResult;
if (rr is TypeResolveResult) {
TypeResolveResult trr = rr as TypeResolveResult;
if (trr.ResolvedClass == null)
return;
list.Items.Add(new XamlCodeCompletionItem("/" + trr.ResolvedClass.Name, trr.ResolvedClass));
} else if (rr is MemberResolveResult && prr != null) {
list.Items.Add(new XamlCodeCompletionItem("/" + context.ParentElement.FullXmlName, trr.ResolvedClass));
} else if (rr is MemberResolveResult) {
MemberResolveResult mrr = rr as MemberResolveResult;
if (mrr.ResolvedMember == null)
return;
list.Items.Add(new XamlCodeCompletionItem("/" + prr.ResolvedType.Name + "." + mrr.ResolvedMember.Name, mrr.ResolvedMember));
list.Items.Add(new XamlCodeCompletionItem("/" + context.ParentElement.FullXmlName, mrr.ResolvedMember));
}
}
}
@ -533,7 +558,7 @@ namespace ICSharpCode.XamlBinding @@ -533,7 +558,7 @@ namespace ICSharpCode.XamlBinding
break;
case "System.Windows.Markup.TypeExtension":
if (context.AttributeValue.ExtensionValue.PositionalArguments.Count <= 1) {
list.Items.AddRange(CreateElementList(context, true));
list.Items.AddRange(CreateElementList(context, true, true));
AttributeValue selItem = Utils.GetInnermostMarkupExtensionInfo(context.AttributeValue.ExtensionValue)
.PositionalArguments.LastOrDefault();
string word = context.Editor.GetWordBeforeCaret().TrimEnd();
@ -589,7 +614,7 @@ namespace ICSharpCode.XamlBinding @@ -589,7 +614,7 @@ namespace ICSharpCode.XamlBinding
// return nothing
break;
case "System.Type":
foreach (var item in CreateElementList(context, true))
foreach (var item in CreateElementList(context, true, true))
yield return item;
break;
default:
@ -661,12 +686,19 @@ namespace ICSharpCode.XamlBinding @@ -661,12 +686,19 @@ namespace ICSharpCode.XamlBinding
IList<ICompletionItem> list = new List<ICompletionItem>();
list.Add(new NewEventCompletionItem(evt, (string.IsNullOrEmpty(name) ? item.Name : name)));
return CompletionDataHelper.AddMatchingEventHandlers(context, invoker).Concat(list);
}
return Enumerable.Empty<ICompletionItem>();
}
static IMember ResolveAttribute(QualifiedNameWithLocation attribute, XamlCompletionContext context)
{
if (attribute == null)
return null;
return ResolveAttribute(attribute.FullXmlName, context);
}
static IMember ResolveAttribute(string attribute, XamlCompletionContext context)
{

3
src/AddIns/BackendBindings/XamlBinding/XamlBinding/QualifiedNameWithLocation.cs

@ -39,10 +39,11 @@ namespace ICSharpCode.XamlBinding @@ -39,10 +39,11 @@ namespace ICSharpCode.XamlBinding
public string FullXmlName {
get {
string name = Prefix;
if (!string.IsNullOrEmpty(name))
name += ":";
name += Name;
name += Name;
return name;
}
}

32
src/AddIns/BackendBindings/XamlBinding/XamlBinding/Utils.cs

@ -136,7 +136,12 @@ namespace ICSharpCode.XamlBinding @@ -136,7 +136,12 @@ namespace ICSharpCode.XamlBinding
public static string GetXamlNamespacePrefix(XamlContext context)
{
var item = context.XmlnsDefinitions.FirstOrDefault(i => i.Value == CompletionDataHelper.XamlNamespace);
return GetNamespacePrefix(CompletionDataHelper.XamlNamespace, context);
}
public static string GetNamespacePrefix(string namespaceUri, XamlContext context)
{
var item = context.XmlnsDefinitions.FirstOrDefault(i => i.Value == namespaceUri);
if (item.Key != null)
return item.Key;
@ -206,7 +211,7 @@ namespace ICSharpCode.XamlBinding @@ -206,7 +211,7 @@ namespace ICSharpCode.XamlBinding
return (offsetStack.Count > 0) ? offsetStack.Pop() : -1;
}
static QualifiedNameWithLocation ResolveCurrentElement(string text, int offset, Dictionary<string, string> xmlnsDefinitions)
{
if (offset < 0)
@ -241,15 +246,22 @@ namespace ICSharpCode.XamlBinding @@ -241,15 +246,22 @@ namespace ICSharpCode.XamlBinding
}
public static void LookUpInfoAtTarget(string fileContent, int caretLine, int caretColumn, int offset,
out Dictionary<string, string> xmlns, out QualifiedNameWithLocation active,
out Dictionary<string, string> xmlns, out List<string> ignoredXmlns, out QualifiedNameWithLocation active,
out QualifiedNameWithLocation parent, out int activeElementStartIndex, out bool isRoot)
{
{
Stack<QualifiedNameWithLocation> stack = new Stack<QualifiedNameWithLocation>();
isRoot = false;
XmlTextReader r = new XmlTextReader(new StringReader(fileContent));
r.XmlResolver = null;
char[] separators = new char[] {
' ', '\t', '\n', '\r'
};
ignoredXmlns = new List<string>();
try {
r.WhitespaceHandling = WhitespaceHandling.Significant;
// move reader to correct position
@ -261,6 +273,18 @@ namespace ICSharpCode.XamlBinding @@ -261,6 +273,18 @@ namespace ICSharpCode.XamlBinding
case XmlNodeType.Element:
if (!r.IsEmptyElement)
stack.Push(new QualifiedNameWithLocation(r.LocalName, r.NamespaceURI, r.Prefix, r.LineNumber, r.LinePosition));
if (r.HasAttributes) {
r.MoveToFirstAttribute();
do {
if (r.NamespaceURI == CompletionDataHelper.MarkupCompatibilityNamespace) {
if (r.LocalName == "Ignorable") {
ignoredXmlns.AddRange(r.Value.Split(separators, StringSplitOptions.RemoveEmptyEntries));
} else if (r.LocalName == "ProcessContent") {
// TODO : add support for ProcessContent
}
}
} while (r.MoveToNextAttribute());
}
break;
}
}

35
src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlCodeCompletionBinding.cs

@ -63,7 +63,7 @@ namespace ICSharpCode.XamlBinding @@ -63,7 +63,7 @@ namespace ICSharpCode.XamlBinding
}
break;
case '{': // starting point for Markup Extension Completion
if (!string.IsNullOrEmpty(context.AttributeName)
if (context.AttributeName != null
&& XmlParser.IsInsideAttributeValue(editor.Document.Text, editor.Caret.Offset)
&& !(context.RawAttributeValue.StartsWith("{}") && context.RawAttributeValue.Length != 2)) {
editor.Document.Insert(editor.Caret.Offset, "{}");
@ -85,7 +85,7 @@ namespace ICSharpCode.XamlBinding @@ -85,7 +85,7 @@ namespace ICSharpCode.XamlBinding
break;
case ':':
if (context.ActiveElement != null && XmlParser.GetQualifiedAttributeNameAtIndex(editor.Document.Text, editor.Caret.Offset) == null) {
if (!context.AttributeName.StartsWith("xmlns")) {
if (!context.AttributeName.Name.StartsWith("xmlns")) {
list = CompletionDataHelper.CreateListForContext(context);
list.PreselectionLength = editor.GetWordBeforeCaretExtended().Length;
editor.ShowCompletionWindow(list);
@ -128,7 +128,10 @@ namespace ICSharpCode.XamlBinding @@ -128,7 +128,10 @@ namespace ICSharpCode.XamlBinding
if (!string.IsNullOrEmpty(starter))
return CodeCompletionKeyPressResult.None;
trackForced = false;
if (!context.AttributeName.StartsWith("xmlns"))
string attributeName = (context.AttributeName != null) ? context.AttributeName.Name : string.Empty;
if (!attributeName.StartsWith("xmlns"))
this.CtrlSpace(editor);
trackForced = true;
return CodeCompletionKeyPressResult.CompletedIncludeKeyInCompletion;
@ -153,11 +156,11 @@ namespace ICSharpCode.XamlBinding @@ -153,11 +156,11 @@ namespace ICSharpCode.XamlBinding
return true;
} else {
// DO NOT USE CompletionDataHelper.CreateListForContext here!!! results in endless recursion!!!!
if (!string.IsNullOrEmpty(context.AttributeName)) {
if (context.AttributeName != null) {
if (!DoMarkupExtensionCompletion(context)) {
var completionList = new XamlCompletionItemList();
var mrr = XamlResolver.Resolve(context.AttributeName, context) as MemberResolveResult;
var mrr = XamlResolver.Resolve(context.AttributeName.FullXmlName, context) as MemberResolveResult;
if (mrr != null && mrr.ResolvedType != null) {
var c = mrr.ResolvedType.GetUnderlyingClass();
@ -170,14 +173,19 @@ namespace ICSharpCode.XamlBinding @@ -170,14 +173,19 @@ namespace ICSharpCode.XamlBinding
completionList.PreselectionLength = editor.GetWordBeforeCaretExtended().Length;
if (context.AttributeName.Name == "TypeArguments" && context.AttributeName.Namespace == CompletionDataHelper.XamlNamespace)
DoTypeArgumentsCompletion(context, completionList);
completionList.SortItems();
if (context.AttributeName.StartsWith("xmlns"))
if (context.AttributeName.Prefix.Equals("xmlns", StringComparison.OrdinalIgnoreCase) ||
context.AttributeName.Name.Equals("xmlns", StringComparison.OrdinalIgnoreCase))
completionList.Items.AddRange(CompletionDataHelper.CreateListForXmlnsCompletion(context.ParseInformation.BestCompilationUnit.ProjectContent));
ICompletionListWindow window = editor.ShowCompletionWindow(completionList);
if (context.AttributeName.StartsWith("xmlns"))
if (context.AttributeName.Prefix.Equals("xmlns", StringComparison.OrdinalIgnoreCase) ||
context.AttributeName.Name.Equals("xmlns", StringComparison.OrdinalIgnoreCase))
window.Width = 400;
}
return true;
@ -187,6 +195,17 @@ namespace ICSharpCode.XamlBinding @@ -187,6 +195,17 @@ namespace ICSharpCode.XamlBinding
return false;
}
static void DoTypeArgumentsCompletion(XamlCompletionContext context, XamlCompletionItemList completionList) {
completionList.Items.AddRange(CompletionDataHelper.CreateElementList(context, false, true));
if (context.ValueStartOffset < 1)
return;
string starter = context.Editor.GetWordBeforeCaretExtended();
int lastComma = starter.LastIndexOf(',');
if (lastComma > -1)
starter = starter.Substring(lastComma).TrimStart(',', ' ', '\t');
completionList.PreselectionLength = starter.Length;
}
static void DoSetterAndEventSetterCompletion(XamlCompletionContext context, XamlCompletionItemList completionList) {
int offset = Utils.GetParentElementStart(context.Editor);
var loc = context.Editor.Document.OffsetToPosition(offset);
@ -205,7 +224,7 @@ namespace ICSharpCode.XamlBinding @@ -205,7 +224,7 @@ namespace ICSharpCode.XamlBinding
}
if (typeName != null) {
switch (context.AttributeName) {
switch (context.AttributeName.Name) {
case "Value":
var loc2 = context.Editor.Document.OffsetToPosition(XmlParser.GetActiveElementStartIndex(context.Editor.Document.Text, context.Editor.Caret.Offset));
AttributeValue propType = MarkupExtensionParser.ParseValue(

92
src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlColorizer.cs

@ -71,10 +71,29 @@ namespace ICSharpCode.XamlBinding @@ -71,10 +71,29 @@ namespace ICSharpCode.XamlBinding
public bool CompletedSuccessfully {
get {
return task.IsCompleted && task.Status == Tasks.TaskStatus.RanToCompletion;
return task.IsCompleted && task.Status == Tasks.TaskStatus.RanToCompletion && !Invalid;
}
}
public bool Invalid { get; set; }
public void Invalidate(string fileContent, string fileName, DocumentLine currentLine, TextView textView)
{
task.Cancel();
this.Invalid = false;
this.FileContent = fileContent;
this.FileName = fileName;
this.textView = textView;
this.LineNumber = currentLine.LineNumber;
this.LineText = currentLine.Text;
this.Offset = currentLine.Offset;
this.task = new System.Threading.Tasks.Task(Process);
this.task.Start();
}
void Process()
{
List<Highlight> results = new List<Highlight>();
@ -82,6 +101,9 @@ namespace ICSharpCode.XamlBinding @@ -82,6 +101,9 @@ namespace ICSharpCode.XamlBinding
foreach (HighlightingInfo info in GetInfo()) {
IMember member = null;
if (task.IsCancellationRequested)
return;
if (!info.Token.StartsWith("xmlns")) {
MemberResolveResult rr = new XamlResolver().Resolve(info.GetExpressionResult(), info.Context.ParseInformation, FileContent) as MemberResolveResult;
member = (rr != null) ? rr.ResolvedMember : null;
@ -90,7 +112,10 @@ namespace ICSharpCode.XamlBinding @@ -90,7 +112,10 @@ namespace ICSharpCode.XamlBinding
results.Add(new Highlight() { Member = member, Info = info });
}
this.results = results;
lock (this) {
this.results = results;
this.Invalid = false;
}
WorkbenchSingleton.SafeThreadAsyncCall(InvokeRedraw);
}
@ -113,9 +138,9 @@ namespace ICSharpCode.XamlBinding @@ -113,9 +138,9 @@ namespace ICSharpCode.XamlBinding
index = LineText.IndexOfAny(index + 1, '=', '.');
if (index > -1) {
context = CompletionDataHelper.ResolveContext(FileContent, FileName, LineNumber, index);
string elementName = context.ActiveElement.Name;
string elementName = context.ActiveElement.FullXmlName;
int propertyNameIndex = elementName.IndexOf('.');
string attribute = context.AttributeName;
string attribute = (context.AttributeName != null) ? context.AttributeName.FullXmlName : string.Empty;
if (attribute.Contains(".")) {
int tmp = attribute.IndexOf('.');
index += attribute.Substring(tmp).Length;
@ -185,20 +210,51 @@ namespace ICSharpCode.XamlBinding @@ -185,20 +210,51 @@ namespace ICSharpCode.XamlBinding
}
}
}
ColorizeInvalidated();
}
void ColorizeMember(HighlightingInfo info, DocumentLine line, IMember member)
{
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);
else
Core.LoggingService.Debug(info.Token + " not highlighted; line " + line.LineNumber);
try {
if (info.Context.IgnoredXmlns.Any(item => info.Token.StartsWith(item + ":"))) {
ChangeLinePart(line.Offset + info.StartOffset, line.Offset + info.EndOffset, HighlightIgnored);
} else {
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") || info.Token.StartsWith(Utils.GetNamespacePrefix(CompletionDataHelper.MarkupCompatibilityNamespace, info.Context) + ":"))
ChangeLinePart(line.Offset + info.StartOffset, line.Offset + info.EndOffset, HighlightNamespaceDeclaration);
else
Core.LoggingService.Debug(info.Token + " not highlighted; line " + line.LineNumber);
}
}
} catch (ArgumentOutOfRangeException) {
highlightCache.Remove(line);
}
}
void ColorizeInvalidated()
{
foreach (var item in highlightCache) {
if (item.Value.Invalid) {
item.Value.Invalidate(this.fileContent, this.fileName, item.Key, this.TextView);
}
}
}
void InvalidateLines(DocumentLine line)
{
DocumentLine current = line;
while (current != null) {
HighlightTask task;
if (highlightCache.TryGetValue(current, out task)) {
task.Invalid = true;
}
current = current.NextLine;
}
}
@ -220,14 +276,22 @@ namespace ICSharpCode.XamlBinding @@ -220,14 +276,22 @@ namespace ICSharpCode.XamlBinding
element.TextRunProperties.SetBackgroundBrush(settings.NamespaceDeclarationBackgroundBrush);
}
void HighlightIgnored(VisualLineElement element)
{
element.TextRunProperties.SetForegroundBrush(settings.IgnoredForegroundBrush);
element.TextRunProperties.SetBackgroundBrush(settings.IgnoredBackgroundBrush);
}
public void BeforeRemoveLine(DocumentLine line)
{
highlightCache.Remove(line);
InvalidateLines(line.NextLine);
}
public void SetLineLength(DocumentLine line, int newTotalLength)
{
highlightCache.Remove(line);
InvalidateLines(line.NextLine);
}
public void LineInserted(DocumentLine insertionPos, DocumentLine newLine)

6
src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlColorizerSettings.cs

@ -21,6 +21,9 @@ namespace ICSharpCode.XamlBinding @@ -21,6 +21,9 @@ namespace ICSharpCode.XamlBinding
public Brush NamespaceDeclarationForegroundBrush { get; set; }
public Brush NamespaceDeclarationBackgroundBrush { get; set; }
public Brush IgnoredForegroundBrush { get; set; }
public Brush IgnoredBackgroundBrush { get; set; }
public XamlColorizerSettings()
{
this.PropertyBackgroundBrush = Brushes.Transparent;
@ -31,6 +34,9 @@ namespace ICSharpCode.XamlBinding @@ -31,6 +34,9 @@ namespace ICSharpCode.XamlBinding
this.NamespaceDeclarationBackgroundBrush = Brushes.Transparent;
this.NamespaceDeclarationForegroundBrush = Brushes.Orange;
this.IgnoredBackgroundBrush = Brushes.Transparent;
this.IgnoredForegroundBrush = Brushes.LightGray;
}
}
}

4
src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlContext.cs

@ -21,7 +21,7 @@ namespace ICSharpCode.XamlBinding @@ -21,7 +21,7 @@ namespace ICSharpCode.XamlBinding
public class XamlContext : ExpressionContext {
public QualifiedNameWithLocation ActiveElement { get; set; }
public QualifiedNameWithLocation ParentElement { get; set; }
public string AttributeName { get; set; }
public QualifiedNameWithLocation AttributeName { get; set; }
public AttributeValue AttributeValue { get; set; }
public string RawAttributeValue { get; set; }
public int ValueStartOffset { get; set; }
@ -29,6 +29,7 @@ namespace ICSharpCode.XamlBinding @@ -29,6 +29,7 @@ namespace ICSharpCode.XamlBinding
public Dictionary<string, string> XmlnsDefinitions { get; set; }
public ParseInformation ParseInformation { get; set; }
public bool InRoot { get; set; }
public List<string> IgnoredXmlns { get; set; }
public XamlContext() {}
@ -53,6 +54,7 @@ namespace ICSharpCode.XamlBinding @@ -53,6 +54,7 @@ namespace ICSharpCode.XamlBinding
this.ValueStartOffset = context.ValueStartOffset;
this.XmlnsDefinitions = context.XmlnsDefinitions;
this.InRoot = context.InRoot;
this.IgnoredXmlns = context.IgnoredXmlns;
}
public char PressedKey { get; set; }

2
src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlResolver.cs

@ -47,7 +47,7 @@ namespace ICSharpCode.XamlBinding @@ -47,7 +47,7 @@ namespace ICSharpCode.XamlBinding
case XamlContextDescription.InTag:
return ResolveAttribute(resolveExpression) ?? ResolveElementName(resolveExpression);
case XamlContextDescription.InAttributeValue:
MemberResolveResult mrr = ResolveAttribute(context.AttributeName);
MemberResolveResult mrr = ResolveAttribute(context.AttributeName.FullXmlName);
if (mrr != null) {
var rr = ResolveAttributeValue(mrr.ResolvedMember, resolveExpression) ?? mrr;
return rr;

9
src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlParser.cs

@ -264,6 +264,15 @@ namespace ICSharpCode.XmlEditor @@ -264,6 +264,15 @@ namespace ICSharpCode.XmlEditor
ignoreEqualsSign = true;
} else if (ch == '=') {
// Do nothing.
} else if (char.IsWhiteSpace(ch)) {
// fix if index is after an equals sign
int oldIndex = index;
// move back to first non-whitespace
while (index > -1 && char.IsWhiteSpace(xml[index]))
index--;
// if no equals sign is found reset index
if (index > -1 && xml[index] != '=')
index = oldIndex;
} else {
return String.Empty;
}

Loading…
Cancel
Save