diff --git a/src/AddIns/BackendBindings/XamlBinding/XamlBinding.Tests/ResolveContextTests.cs b/src/AddIns/BackendBindings/XamlBinding/XamlBinding.Tests/ResolveContextTests.cs index 4d3fbff9df..6bc601b575 100644 --- a/src/AddIns/BackendBindings/XamlBinding/XamlBinding.Tests/ResolveContextTests.cs +++ b/src/AddIns/BackendBindings/XamlBinding/XamlBinding.Tests/ResolveContextTests.cs @@ -69,6 +69,15 @@ namespace ICSharpCode.XamlBinding.Tests Assert.AreEqual(XamlContextDescription.InTag, context.Description); } + [Test] + public void ElementNameWithDotTest1() + { + string xaml = "\n\t\n"; + 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 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]); + } } } \ No newline at end of file diff --git a/src/AddIns/BackendBindings/XamlBinding/XamlBinding.Tests/Test2.xaml b/src/AddIns/BackendBindings/XamlBinding/XamlBinding.Tests/Test2.xaml index b13ca628a7..9620a6cc30 100644 --- a/src/AddIns/BackendBindings/XamlBinding/XamlBinding.Tests/Test2.xaml +++ b/src/AddIns/BackendBindings/XamlBinding/XamlBinding.Tests/Test2.xaml @@ -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" > - + \ No newline at end of file diff --git a/src/AddIns/BackendBindings/XamlBinding/XamlBinding.Tests/XmlTests.cs b/src/AddIns/BackendBindings/XamlBinding/XamlBinding.Tests/XmlTests.cs index ebc98f21f9..f0865dfafa 100644 --- a/src/AddIns/BackendBindings/XamlBinding/XamlBinding.Tests/XmlTests.cs +++ b/src/AddIns/BackendBindings/XamlBinding/XamlBinding.Tests/XmlTests.cs @@ -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 = ""; + int offset = ""; + int offset = ""; + int offset = ""; + int offset = ""; + int offset = ""; + int offset = " xmlnsDefs; + List 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 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 return string.Empty; } - public static IList CreateElementList(XamlCompletionContext context, bool classesOnly) + public static IList CreateElementList(XamlCompletionContext context, bool classesOnly, bool includeAbstract) { var items = GetClassesFromContext(context); var result = new List(); @@ -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 public static IEnumerable CreateListOfMarkupExtensions(XamlCompletionContext context) { - var list = CreateElementList(context, true); + var list = CreateElementList(context, true, false); var neededItems = list.OfType() .Where(i => (i.Entity as IClass).DerivesFrom("System.Windows.Markup.MarkupExtension")); @@ -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 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 { 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 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 // 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 IList list = new List(); list.Add(new NewEventCompletionItem(evt, (string.IsNullOrEmpty(name) ? item.Name : name))); - return CompletionDataHelper.AddMatchingEventHandlers(context, invoker).Concat(list); } return Enumerable.Empty(); } + + static IMember ResolveAttribute(QualifiedNameWithLocation attribute, XamlCompletionContext context) + { + if (attribute == null) + return null; + + return ResolveAttribute(attribute.FullXmlName, context); + } static IMember ResolveAttribute(string attribute, XamlCompletionContext context) { diff --git a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/QualifiedNameWithLocation.cs b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/QualifiedNameWithLocation.cs index 0d60d8c2aa..0b070d303e 100644 --- a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/QualifiedNameWithLocation.cs +++ b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/QualifiedNameWithLocation.cs @@ -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; } } diff --git a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/Utils.cs b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/Utils.cs index 5cf25e5bad..47f52d3880 100644 --- a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/Utils.cs +++ b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/Utils.cs @@ -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 return (offsetStack.Count > 0) ? offsetStack.Pop() : -1; } - + static QualifiedNameWithLocation ResolveCurrentElement(string text, int offset, Dictionary xmlnsDefinitions) { if (offset < 0) @@ -241,15 +246,22 @@ namespace ICSharpCode.XamlBinding } public static void LookUpInfoAtTarget(string fileContent, int caretLine, int caretColumn, int offset, - out Dictionary xmlns, out QualifiedNameWithLocation active, + out Dictionary xmlns, out List ignoredXmlns, out QualifiedNameWithLocation active, out QualifiedNameWithLocation parent, out int activeElementStartIndex, out bool isRoot) - { + { Stack stack = new Stack(); isRoot = false; XmlTextReader r = new XmlTextReader(new StringReader(fileContent)); r.XmlResolver = null; + + char[] separators = new char[] { + ' ', '\t', '\n', '\r' + }; + + ignoredXmlns = new List(); + try { r.WhitespaceHandling = WhitespaceHandling.Significant; // move reader to correct position @@ -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; } } diff --git a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlCodeCompletionBinding.cs b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlCodeCompletionBinding.cs index ccb8e72b7c..c820f3f5ef 100644 --- a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlCodeCompletionBinding.cs +++ b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlCodeCompletionBinding.cs @@ -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 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 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 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 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 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 } 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( diff --git a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlColorizer.cs b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlColorizer.cs index b42530adfc..3d5c4fd070 100644 --- a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlColorizer.cs +++ b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlColorizer.cs @@ -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 results = new List(); @@ -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 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 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 } } } + 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 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) diff --git a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlColorizerSettings.cs b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlColorizerSettings.cs index 3d680c1d2f..2739d779a7 100644 --- a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlColorizerSettings.cs +++ b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlColorizerSettings.cs @@ -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 this.NamespaceDeclarationBackgroundBrush = Brushes.Transparent; this.NamespaceDeclarationForegroundBrush = Brushes.Orange; + + this.IgnoredBackgroundBrush = Brushes.Transparent; + this.IgnoredForegroundBrush = Brushes.LightGray; } } } diff --git a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlContext.cs b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlContext.cs index 2ed4d72b21..88fcbb1ea1 100644 --- a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlContext.cs +++ b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlContext.cs @@ -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 public Dictionary XmlnsDefinitions { get; set; } public ParseInformation ParseInformation { get; set; } public bool InRoot { get; set; } + public List IgnoredXmlns { get; set; } public XamlContext() {} @@ -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; } diff --git a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlResolver.cs b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlResolver.cs index df8cad541a..6caff261bb 100644 --- a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlResolver.cs +++ b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlResolver.cs @@ -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; diff --git a/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlParser.cs b/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlParser.cs index 4cca5f066f..8ea1ea0cd8 100644 --- a/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlParser.cs +++ b/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlParser.cs @@ -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; }