From 485f751cc5260e4fc82694104d38f4ce0fbe295f Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Fri, 12 Jun 2009 12:23:07 +0000 Subject: [PATCH] - XAML completion is now a bit less intrusive - removed code duplication from XmlFormattingStrategy - fixed bugs in XAML code completion - added AssemblyName property to IProjectContent - do not close insight and completion windows when they are still needed git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@4280 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Test/Utils/MockProjectContent.cs | 6 + .../XamlBinding.Tests/UtilsTests.cs | 32 +++ .../XamlBinding/XamlBinding.Tests/XmlTests.cs | 4 + .../XamlBinding/CompletionDataHelper.cs | 245 ++++++++++++++---- .../XamlBinding/XamlBinding/Extensions.cs | 32 ++- .../XamlBinding/MarkupExtensionParser.cs | 3 + .../XamlBinding/XamlBinding/Utils.cs | 74 +++++- .../XamlBinding/XamlBinding/XamlBinding.addin | 4 + .../XamlBinding/XamlCodeCompletionBinding.cs | 54 ++-- .../XamlBinding/XamlCompletionItem.cs | 91 ++++++- .../XamlBinding/XamlCompletionItemList.cs | 33 ++- .../XamlBinding/XamlBinding/XamlContext.cs | 5 + .../AvalonEdit.AddIn/Src/CodeEditor.cs | 12 +- .../XmlEditor/Project/Src/FormatXmlCommand.cs | 10 +- .../Project/Src/XmlFormattingStrategy.cs | 35 ++- .../XmlEditor/Project/Src/XmlTreeView.cs | 4 +- .../XmlEditor/Project/Src/XmlView.cs | 26 +- .../XmlEditor/Project/XmlEditor.csproj | 5 + .../Test/Utils/MockProjectContent.cs | 6 + .../Project/Src/Gui/Dialogs/NewFileDialog.cs | 2 +- .../ParserService/ParseProjectContent.cs | 7 +- .../ProjectContent/DefaultProjectContent.cs | 7 + .../Src/ProjectContent/IProjectContent.cs | 7 + .../ReflectionProjectContent.cs | 6 + 24 files changed, 558 insertions(+), 152 deletions(-) diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/MockProjectContent.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/MockProjectContent.cs index 64eda64168..408ba9a285 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/MockProjectContent.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/MockProjectContent.cs @@ -354,5 +354,11 @@ namespace PythonBinding.Tests.Utils { throw new NotImplementedException(); } + + public string AssemblyName { + get { + throw new NotImplementedException(); + } + } } } diff --git a/src/AddIns/BackendBindings/XamlBinding/XamlBinding.Tests/UtilsTests.cs b/src/AddIns/BackendBindings/XamlBinding/XamlBinding.Tests/UtilsTests.cs index 8b1529bbc2..912c751015 100644 --- a/src/AddIns/BackendBindings/XamlBinding/XamlBinding.Tests/UtilsTests.cs +++ b/src/AddIns/BackendBindings/XamlBinding/XamlBinding.Tests/UtilsTests.cs @@ -98,5 +98,37 @@ namespace ICSharpCode.XamlBinding.Tests Assert.AreEqual(expectedResult, actualResult); } + + [Test] + public void ExistingAttributesTest() + { + string xaml = " { "xmlns", "xmlns:x", "xmlns:toolkit", "xmlns:chartingToolkit" }; + + Assert.AreEqual(expected.Count, list.Length, "Wrong count!"); + Assert.AreEqual(list, expected, "Wrong elements!"); + } + + [Test] + public void ExistingAttributesWithInvalidSyntaxTest() + { + string xaml = " { "xmlns", "xmlns:x", "xmlns:toolkit", "xmlns:chartingToolkit" }; + + Assert.AreEqual(expected.Count, list.Length, "Wrong count!"); + Assert.AreEqual(list, expected, "Wrong elements!"); + } } } diff --git a/src/AddIns/BackendBindings/XamlBinding/XamlBinding.Tests/XmlTests.cs b/src/AddIns/BackendBindings/XamlBinding/XamlBinding.Tests/XmlTests.cs index 6731151cb0..ebc98f21f9 100644 --- a/src/AddIns/BackendBindings/XamlBinding/XamlBinding.Tests/XmlTests.cs +++ b/src/AddIns/BackendBindings/XamlBinding/XamlBinding.Tests/XmlTests.cs @@ -66,6 +66,8 @@ namespace ICSharpCode.XamlBinding.Tests int offset = "$Revision$ // -using ICSharpCode.SharpDevelop.Editor.CodeCompletion; +using ICSharpCode.SharpDevelop.Project; using System; using System.Collections.Generic; using System.Diagnostics; @@ -15,6 +15,7 @@ using System.Xml; using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop.Dom; using ICSharpCode.SharpDevelop.Editor; +using ICSharpCode.SharpDevelop.Editor.CodeCompletion; using ICSharpCode.XmlEditor; using LoggingService = ICSharpCode.Core.LoggingService; @@ -32,6 +33,10 @@ namespace ICSharpCode.XamlBinding static readonly List standardAttributes = new List { new DefaultCompletionItem("xmlns:") }; + + static readonly List xamlNamespaceAttributes = new List { + "Class", "ClassModifier", "FieldModifier", "Name", "Subclass", "TypeArguments", "Uid" + }; #endregion public const string XamlNamespace = "http://schemas.microsoft.com/winfx/2006/xaml"; @@ -62,7 +67,7 @@ namespace ICSharpCode.XamlBinding XamlContextDescription description = XamlContextDescription.InTag; if (path == null || path.Elements.Count == 0) { - description = XamlContextDescription.AtTag; + description = XamlContextDescription.None; path = XmlParser.GetParentElementPath(text.Substring(0, offset)); } else { int ltOffset = XmlParser.GetActiveElementStartIndex(text, offset); @@ -71,7 +76,7 @@ namespace ICSharpCode.XamlBinding else { string space = text.Substring(ltOffset + 1, offset - ltOffset - 1); var last = path.Elements.LastOrDefault(); - if (last != null && last.ToString().Equals(space, StringComparison.Ordinal)) + if (last != null && last.ToString().StartsWith(space, StringComparison.Ordinal)) description = XamlContextDescription.AtTag; } } @@ -101,31 +106,96 @@ namespace ICSharpCode.XamlBinding return context; } - static List CreateListForAttributeName(ParseInformation parseInfo, XamlExpressionContext context, string[] existingItems) + static List CreateListForAttributeName(ITextEditor editor, ParseInformation parseInfo, XamlExpressionContext context, string[] existingItems) { if (context.ElementPath.Elements.Count == 0) return null; - QualifiedName lastElement = context.ElementPath.Elements[context.ElementPath.Elements.Count - 1]; + QualifiedName lastElement = context.ElementPath.Elements.LastOrDefault(); XamlCompilationUnit cu = parseInfo.BestCompilationUnit as XamlCompilationUnit; if (cu == null) return null; - IReturnType rt = cu.CreateType(lastElement.Namespace, lastElement.Name); + IReturnType rt = cu.CreateType(lastElement.Namespace, lastElement.Name.Trim('.')); if (rt == null) return null; var list = new List(); + + string xamlPrefix = Utils.GetXamlNamespacePrefix(editor.Document.Text, editor.Caret.Offset); + + foreach (string item in xamlNamespaceAttributes) { + if (!existingItems.Contains(xamlPrefix + ":" + item)) + list.Add(new XamlCompletionItem(xamlPrefix, XamlNamespace, item)); + } + foreach (IProperty p in rt.GetProperties()) { if (p.IsPublic && p.CanSet && !existingItems.Contains(p.Name)) { - list.Add(new XamlCompletionItem(p)); + list.Add(new XamlCodeCompletionItem(p)); } } foreach (IEvent e in rt.GetEvents()) { if (e.IsPublic && !existingItems.Contains(e.Name)) { - list.Add(new XamlCompletionItem(e)); + list.Add(new XamlCodeCompletionItem(e)); } } return list; } + public static IEnumerable CreateListForXmlnsCompletion(IProjectContent projectContent) + { + List list = new List(); + + foreach (IProjectContent content in projectContent.ReferencedContents) { + foreach (IAttribute att in content.GetAssemblyAttributes()) { + if (att.PositionalArguments.Count == 2 + && att.AttributeType.FullyQualifiedName == "System.Windows.Markup.XmlnsDefinitionAttribute") { + list.Add(new XmlnsCompletionItem(att.PositionalArguments[0] as string, true)); + } + } + + foreach (string @namespace in content.NamespaceNames) { + if (!string.IsNullOrEmpty(@namespace)) + list.Add(new XmlnsCompletionItem(@namespace, content.AssemblyName)); + } + } + + foreach (string @namespace in projectContent.NamespaceNames) { + if (!string.IsNullOrEmpty(@namespace)) + list.Add(new XmlnsCompletionItem(@namespace, false)); + } + + return list + .Distinct(new XmlnsEqualityComparer()) + .OrderBy(item => item, new XmlnsComparer()) + .Cast(); + } + + sealed class XmlnsEqualityComparer : IEqualityComparer { + public bool Equals(XmlnsCompletionItem x, XmlnsCompletionItem y) + { + return x.Namespace == y.Namespace && x.Assembly == y.Assembly; + } + + public int GetHashCode(XmlnsCompletionItem obj) + { + return string.IsNullOrEmpty(obj.Assembly) ? obj.Namespace.GetHashCode() : obj.Namespace.GetHashCode() ^ obj.Assembly.GetHashCode(); + } + } + + sealed class XmlnsComparer : IComparer { + public int Compare(XmlnsCompletionItem x, XmlnsCompletionItem y) + { + if (x.IsUrl && y.IsUrl) + return x.Namespace.CompareTo(y.Namespace); + if (x.IsUrl) + return -1; + if (y.IsUrl) + return 1; + if (x.Assembly == y.Assembly) + return x.Namespace.CompareTo(y.Namespace); + else + return x.Assembly.CompareTo(y.Assembly); + } + } + static bool IsReaderAtTarget(XmlTextReader r, int caretLine, int caretColumn) { if (r.LineNumber > caretLine) @@ -136,18 +206,18 @@ namespace ICSharpCode.XamlBinding return false; } - public static IList CreateListForElement(ParseInformation parseInfo, string fileContent, int caretLine, int caretColumn) + public static IList CreateListForElement(ParseInformation parseInfo, string fileContent, int caretLine, int caretColumn, bool addOpeningBrace) { var items = GetClassesFromContext(parseInfo, fileContent, caretLine, caretColumn); var result = new List(); foreach (var ns in items) { - result.AddRange(from c in ns.Value - where (c.ClassType == ClassType.Class && - !c.IsAbstract && !c.IsStatic && - !c.ClassInheritanceTree.Any(b => b.FullyQualifiedName == "System.Attribute") && - c.Methods.Any(m => m.IsConstructor && m.IsPublic)) - select (new XamlCompletionItem(c, ns.Key) as ICompletionItem) + result.AddRange((from c in ns.Value + where (c.ClassType == ClassType.Class && + !c.IsAbstract && !c.IsStatic && + !c.ClassInheritanceTree.Any(b => b.FullyQualifiedName == "System.Attribute") && + c.Methods.Any(m => m.IsConstructor && m.IsPublic)) + select (new XamlCodeCompletionItem(c, ns.Key, addOpeningBrace))).Cast() ); } @@ -156,20 +226,21 @@ namespace ICSharpCode.XamlBinding public static IList CreateListOfMarkupExtensions(ParseInformation parseInfo, string fileContent, int caretLine, int caretColumn) { - var list = CreateListForElement(parseInfo, fileContent, caretLine, caretColumn); + var list = CreateListForElement(parseInfo, fileContent, caretLine, caretColumn, false); var neededItems = list - .Where(i => ((i as XamlCompletionItem).Entity as IClass).ClassInheritanceTree + .Where(i => ((i as XamlCodeCompletionItem).Entity as IClass).ClassInheritanceTree .Any(item => item.FullyQualifiedName == "System.Windows.Markup.MarkupExtension")) .Select( selItem => { - var it = selItem as XamlCompletionItem; + var it = selItem as XamlCodeCompletionItem; string text = it.Text; if (it.Text.EndsWith("Extension", StringComparison.Ordinal)) text = text.Remove(it.Text.Length - "Extension".Length); - return new XamlCompletionItem(text, it.Entity) as ICompletionItem; + return new XamlCodeCompletionItem(it.Entity, text); } - ); + ) + .Cast(); return neededItems.ToList(); } @@ -180,13 +251,23 @@ namespace ICSharpCode.XamlBinding ParseInformation info = ParserService.GetParseInformation(editor.FileName); switch (context.Description) { + case XamlContextDescription.None: + if (context.Forced) { + list.Items.AddRange(standardElements.Select(item => new DefaultCompletionItem("<" + item.Text)).Cast()); + list.Items.AddRange(CreateListForElement(info, editor.Document.Text, editor.Caret.Line, editor.Caret.Column, true)); + } + break; case XamlContextDescription.AtTag: list.Items.AddRange(standardElements); - list.Items.AddRange(CreateListForElement(info, editor.Document.Text, editor.Caret.Line, editor.Caret.Column)); + if (editor.Document.GetCharAt(editor.Caret.Offset - 1) == '.' || context.PressedKey == '.') { + var existing = Utils.GetListOfExistingAttributeNames(editor.Document.Text, Utils.GetParentElementStart(editor)); + list.Items.AddRange(CreateListForAttributeName(editor, info, new XamlExpressionContext(context.Path, null, false), existing).RemoveEvents()); + } else + list.Items.AddRange(CreateListForElement(info, editor.Document.Text, editor.Caret.Line, editor.Caret.Column, false)); break; case XamlContextDescription.InTag: - var existing = Utils.GetListOfExistingAttributeNames(editor.Document.Text, editor.Caret.Offset); - list.Items.AddRange(CreateListForAttributeName(info, new XamlExpressionContext(context.Path, null, false), existing)); + var existingAttribs = Utils.GetListOfExistingAttributeNames(editor.Document.Text, editor.Caret.Offset); + list.Items.AddRange(CreateListForAttributeName(editor, info, new XamlExpressionContext(context.Path, null, false), existingAttribs)); QualifiedName last = context.Path.Elements[context.Path.Elements.Count - 1]; @@ -194,10 +275,11 @@ namespace ICSharpCode.XamlBinding if (trr != null && trr.ResolvedType != null && trr.ResolvedType.GetUnderlyingClass() != null) { if (trr.ResolvedType.GetUnderlyingClass().ClassInheritanceTree.Any(i => i.FullyQualifiedName == "System.Windows.DependencyObject")) { - list.Items.AddRange(GetListOfAttachedProperties(info, editor.Document.Text, editor.Caret.Line, editor.Caret.Column, existing)); - list.Items.AddRange(GetListOfAttachedEvents(info, editor.Document.Text, editor.Caret.Line, editor.Caret.Column, existing)); + list.Items.AddRange(GetListOfAttachedProperties(info, editor.Document.Text, editor.Caret.Line, editor.Caret.Column, existingAttribs)); + list.Items.AddRange(GetListOfAttachedEvents(info, editor.Document.Text, editor.Caret.Line, editor.Caret.Column, existingAttribs)); } } + list.Items.AddRange(standardAttributes); break; case XamlContextDescription.InAttributeValue: @@ -210,6 +292,20 @@ namespace ICSharpCode.XamlBinding return list; } + static bool FilterCollectionAttributes(ICompletionItem item) + { + if (item is XamlCodeCompletionItem) { + var comItem = item as XamlCodeCompletionItem; + if (comItem.Entity is IProperty) { + var prop = comItem.Entity as IProperty; + var c = prop.ReturnType.GetUnderlyingClass(); + return c != null && c.ClassInheritanceTree.Any(b => b.FullyQualifiedName == "System.Collections.IEnumerable"); + } + } + + return false; + } + public static IEnumerable CreateMarkupExtensionInsight(XamlContext context, ParseInformation info, ITextEditor editor) { var markup = GetInnermostMarkup(context.AttributeValue.ExtensionValue); @@ -259,7 +355,7 @@ namespace ICSharpCode.XamlBinding { var ctors = trr.ResolvedType.GetMethods().Where(m => m.IsConstructor && m.Parameters.Count >= markup.PositionalArguments.Count); if (ctors.Any(ctor => ctor.Parameters.Count >= markup.PositionalArguments.Count)) { - list.Items.AddRange(trr.ResolvedType.GetProperties().Select(p => new XamlCompletionItem(p.Name + "=", p) as ICompletionItem)); + list.Items.AddRange(trr.ResolvedType.GetProperties().Select(p => new XamlCodeCompletionItem(p, p.Name + "=")).Cast()); } } @@ -277,7 +373,7 @@ namespace ICSharpCode.XamlBinding case "System.Windows.Markup.TypeExtension": if (context.AttributeValue.ExtensionValue.PositionalArguments.Count == 1 && context.PressedKey == ' ') break; if (context.AttributeValue.ExtensionValue.PositionalArguments.Count <= 1) { - list.Items.AddRange(CreateListForElement(info, editor.Document.Text, editor.Caret.Line, editor.Caret.Column)); + list.Items.AddRange(CreateListForElement(info, editor.Document.Text, editor.Caret.Line, editor.Caret.Column, false)); AttributeValue selItem = context.AttributeValue.ExtensionValue.PositionalArguments.LastOrDefault(); if (selItem != null && selItem.IsString) { string s = selItem.StringValue; @@ -328,7 +424,7 @@ namespace ICSharpCode.XamlBinding switch (c.ClassType) { case ClassType.Enum: foreach (IField f in c.Fields) - yield return new XamlCompletionItem(f); + yield return new XamlCodeCompletionItem(f); break; case ClassType.Struct: if (c.FullyQualifiedName == "System.Boolean") { @@ -343,11 +439,18 @@ namespace ICSharpCode.XamlBinding if (path != null && path.Elements.Count > 0) { var item = path.Elements[path.Elements.Count - 1]; string attribute = XmlParser.GetAttributeNameAtIndex(editor.Document.Text, editor.Caret.Offset); - var e = ResolveAttribute(attribute, editor) as IEvent; - if (e == null) + var evt = ResolveAttribute(attribute, editor) as IEvent; + if (evt == null) break; + + string prefix = Utils.GetXamlNamespacePrefix(editor.Document.Text, editor.Caret.Offset); string name = Utils.GetAttributeValue(editor.Document.Text, editor.Caret.Offset, "name"); - yield return new NewEventCompletionItem(e, (string.IsNullOrEmpty(name)) ? item.Name : name); + if (string.IsNullOrEmpty(name)) + name = Utils.GetAttributeValue(editor.Document.Text, editor.Caret.Offset, (string.IsNullOrEmpty(prefix) ? "" : prefix + ":") + "name"); + + Debug.Print("prefix: " + prefix + " name: " + name); + + yield return new NewEventCompletionItem(evt, (string.IsNullOrEmpty(name)) ? item.Name : name); foreach (var eventItem in CompletionDataHelper.AddMatchingEventHandlers(editor, invoker)) yield return eventItem; @@ -355,6 +458,19 @@ namespace ICSharpCode.XamlBinding } break; } + + switch (c.FullyQualifiedName) { + case "System.Windows.Media.Brush": + foreach (var item in typeof(System.Windows.Media.Brushes).GetProperties()) { + yield return new DefaultCompletionItem(item.Name); + } + break; + case "System.Windows.Media.Color": + foreach (var item in typeof(System.Windows.Media.Colors).GetProperties()) { + yield return new DefaultCompletionItem(item.Name); + } + break; + } } static IEntity ResolveAttribute(string attribute, ITextEditor editor) @@ -401,7 +517,9 @@ namespace ICSharpCode.XamlBinding { var items = GetClassesFromContext(info, editor.Document.Text, editor.Caret.Line, editor.Caret.Column); foreach (var ns in items) { - list.Items.AddRange(ns.Value.Where(c => c.Fields.Any(f => f.IsStatic) || c.Properties.Any(p => p.IsStatic)).Select(c => new XamlCompletionItem(c, ns.Key) as ICompletionItem)); + list.Items.AddRange(ns.Value.Where(c => c.Fields.Any(f => f.IsStatic) || c.Properties.Any(p => p.IsStatic)) + .Select(c => new XamlCodeCompletionItem(c, ns.Key, false)) + .Cast()); } if (selItem != null && selItem.IsString) { string s = selItem.StringValue; @@ -473,7 +591,7 @@ namespace ICSharpCode.XamlBinding break; } if (equal) { - yield return new XamlCompletionItem(m); + yield return new XamlCodeCompletionItem(m); } } } @@ -491,15 +609,35 @@ namespace ICSharpCode.XamlBinding return result; } - static IDictionary> GetClassesFromContext(ParseInformation parseInfo, string fileContent, int caretLine, int caretColumn) + static XmlTextReader CreateReaderAtTarget(string fileContent, int caretLine, int caretColumn) + { + XmlTextReader r = new XmlTextReader(new StringReader(fileContent)); + + try { + r.WhitespaceHandling = WhitespaceHandling.Significant; + // move reader to correct position + while (r.Read() && !IsReaderAtTarget(r, caretLine, caretColumn)) { } + } catch (XmlException) {} + + return r; + } + + static string GetPrefixForNamespace(string @namespace, string fileContent, int caretLine, int caretColumn) { - using (XmlTextReader r = new XmlTextReader(new StringReader(fileContent))) { - try { - r.WhitespaceHandling = WhitespaceHandling.Significant; - // move reader to correct position - while (r.Read() && !IsReaderAtTarget(r, caretLine, caretColumn)) { } - } catch (XmlException) {} + using (XmlTextReader r = CreateReaderAtTarget(fileContent, caretLine, caretColumn)) { + foreach (var item in r.GetNamespacesInScope(XmlNamespaceScope.ExcludeXml)) { + if (item.Value == @namespace) { + return item.Key; + } + } + return string.Empty; + } + } + + static IDictionary> GetClassesFromContext(ParseInformation parseInfo, string fileContent, int caretLine, int caretColumn) + { + using (XmlTextReader r = CreateReaderAtTarget(fileContent, caretLine, caretColumn)) { IProjectContent pc = parseInfo.BestCompilationUnit.ProjectContent; var result = new Dictionary>(); @@ -514,15 +652,8 @@ namespace ICSharpCode.XamlBinding static List GetListOfAttachedProperties(ParseInformation parseInfo, string fileContent, int caretLine, int caretColumn, string[] existingItems) { - using (XmlTextReader r = new XmlTextReader(new StringReader(fileContent))) { - try { - r.WhitespaceHandling = WhitespaceHandling.Significant; - // move reader to correct position - while (r.Read() && !IsReaderAtTarget(r, caretLine, caretColumn)) { } - } - catch (XmlException) { - } - var result = new List(); + using (XmlTextReader r = CreateReaderAtTarget(fileContent, caretLine, caretColumn)) { + List result = new List(); IProjectContent pc = parseInfo.BestCompilationUnit.ProjectContent; foreach (var ns in r.GetNamespacesInScope(XmlNamespaceScope.ExcludeXml)) { @@ -561,10 +692,11 @@ namespace ICSharpCode.XamlBinding string name = (!string.IsNullOrEmpty(ns.Key)) ? ns.Key + ":" : ""; string property = item.Name.Remove(item.Name.Length - "Property".Length); name += c.Name + "." + item.Name.Remove(item.Name.Length - "Property".Length); - return new XamlCompletionItem(name, new DefaultProperty(c, property) { ReturnType = GetAttachedPropertyType(item, c) } ) as ICompletionItem; + return new XamlCodeCompletionItem(new DefaultProperty(c, property) { ReturnType = GetAttachedPropertyType(item, c) }, name); } ) .Where(item => !existingItems.Any(str => str == item.Text)) + .Cast() ); } } @@ -611,14 +743,15 @@ namespace ICSharpCode.XamlBinding result.AddRange(attachedEvents .Select( - item => new XamlCompletionItem( - (string.IsNullOrEmpty(ns.Key) ? "" : ns.Key + ":") + c.Name + "." + item.Name.Remove(item.Name.Length - "Event".Length), - new DefaultEvent(c, GetEventNameFromField(item)) { - ReturnType = GetAttachedEventDelegateType(item, c) - } - ) as ICompletionItem + item => new XamlCodeCompletionItem( + new DefaultEvent(c, GetEventNameFromField(item)) { + ReturnType = GetAttachedEventDelegateType(item, c) + }, + (string.IsNullOrEmpty(ns.Key) ? "" : ns.Key + ":") + c.Name + "." + item.Name.Remove(item.Name.Length - "Event".Length) + ) ) .Where(item => !existingItems.Any(str => str == item.Text)) + .Cast() ); } } diff --git a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/Extensions.cs b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/Extensions.cs index fcf47b117b..c419fce30e 100644 --- a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/Extensions.cs +++ b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/Extensions.cs @@ -5,10 +5,13 @@ // $Revision$ // -using ICSharpCode.SharpDevelop; using System; +using System.Collections.Generic; using System.Linq; + +using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.SharpDevelop.Editor.CodeCompletion; using ICSharpCode.XmlEditor; namespace ICSharpCode.XamlBinding @@ -36,15 +39,26 @@ namespace ICSharpCode.XamlBinding return false; } - public static QualifiedName LastOrDefault(this QualifiedNameCollection collection) + public static IEnumerable RemoveEvents(this IEnumerable list) { - if (collection == null) - throw new ArgumentNullException("collection"); - - if (collection.Count > 0) - return collection[collection.Count - 1]; - - return null; + foreach (var item in list) { + if (item is XamlCodeCompletionItem) { + var comItem = item as XamlCodeCompletionItem; + if (!(comItem.Entity is IEvent)) + yield return item; + } else yield return item; + } + } + + public static IEnumerable RemoveProperties(this IEnumerable list) + { + foreach (var item in list) { + if (item is XamlCodeCompletionItem) { + var comItem = item as XamlCodeCompletionItem; + if (!(comItem.Entity is IProperty)) + yield return item; + } else yield return item; + } } } } diff --git a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/MarkupExtensionParser.cs b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/MarkupExtensionParser.cs index 5fccb320e7..9051b4f0e8 100644 --- a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/MarkupExtensionParser.cs +++ b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/MarkupExtensionParser.cs @@ -27,6 +27,9 @@ namespace ICSharpCode.XamlBinding info.ExtensionType = token.Value; break; case MarkupExtensionTokenKind.MemberName: + // if there is an open member without a value add the member name + if (argumentName != null) + info.NamedArguments.Add(argumentName, new AttributeValue(string.Empty)); argumentName = token.Value; break; case MarkupExtensionTokenKind.String: diff --git a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/Utils.cs b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/Utils.cs index 20f9f7dc92..58ad3bb198 100644 --- a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/Utils.cs +++ b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/Utils.cs @@ -5,13 +5,13 @@ // $Revision$ // +using ICSharpCode.SharpDevelop.Editor; using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Xml; - using ICSharpCode.Core; using ICSharpCode.XmlEditor; @@ -64,7 +64,8 @@ namespace ICSharpCode.XamlBinding if (text == null) return null; - XmlReader reader = XmlTextReader.Create(new StringReader(text)); + XmlTextReader reader = new XmlTextReader(new StringReader(text)); + reader.XmlResolver = null; try { reader.ReadToFollowing("Test"); @@ -74,13 +75,14 @@ namespace ICSharpCode.XamlBinding do { LoggingService.Debug("name: " + reader.Name + " value: " + reader.Value); - int start = reader.Name.IndexOf(':') + 1; - string plainName = reader.Name.Substring(start, reader.Name.Length - start).ToUpperInvariant(); + string plainName = reader.Name.ToUpperInvariant(); if (plainName == name.ToUpperInvariant()) return reader.Value; } while (reader.MoveToNextAttribute()); - } catch (XmlException) { } + } catch (XmlException e) { + Debug.Print(e.ToString()); + } return null; } @@ -183,7 +185,12 @@ namespace ICSharpCode.XamlBinding LoggingService.Debug("name: " + reader.Name + " value: " + reader.Value); list.Add(reader.Name); } while (reader.MoveToNextAttribute()); - } catch (XmlException) { } + } catch (XmlException e) { + Debug.Print(e.ToString()); + } + + foreach (var item in list) + Debug.Print(item); return list.ToArray(); } @@ -203,19 +210,34 @@ namespace ICSharpCode.XamlBinding return startIndex; } + + static char[] whitespace = new char[] {' ', '\t', '\n', '\r'}; static string SimplifyToSingleElement(string text, int offset, string name) { int index = XmlParser.GetActiveElementStartIndex(text, offset); if (index == -1) return null; - index = text.IndexOf(' ', index); + index = text.IndexOfAny(whitespace, index); if (index == -1) return null; - text = text.Substring(index); - int endIndex = text.IndexOfAny(new char[] { '<', '>' }); - if (endIndex == -1) return null; - text = text.Substring(0, endIndex).Trim(' ', '\t', '\n', '\r', '/'); - LoggingService.Debug("text: '" + text + "'"); - text = "<" + name + " " + text + " />"; + string newText = text.Substring(index); + int endIndex = newText.IndexOfAny(new char[] { '<', '>' }); + if (endIndex == -1) + endIndex = newText.Length; + newText = newText.Substring(0, endIndex).Trim(' ', '\t', '\n', '\r', '/'); + LoggingService.Debug("text: '" + newText + "'"); + if (!newText.EndsWith("\"") && newText.LastIndexOfAny(whitespace) > -1) { + newText = newText.Substring(0, newText.LastIndexOfAny(whitespace)); + } + + string namespaceDecls = ""; + + var list = Utils.GetXmlNamespacesForOffset(text, offset); + + foreach (var item in list) { + namespaceDecls += item.Key + "=\"" + item.Value + "\" "; + } + + text = "<" + name + " " + newText + " " + namespaceDecls + " />"; return text; } @@ -237,7 +259,7 @@ namespace ICSharpCode.XamlBinding if (offset < 0) throw new ArgumentOutOfRangeException("offset", offset, "Value must be between 0 and " + (xaml.Length - 1)); - if (offset >= xaml.Length) + if (offset >= xaml.Length && offset > 0) offset = xaml.Length - 1; string interestingPart = xaml.Substring(0, offset); @@ -247,5 +269,29 @@ namespace ICSharpCode.XamlBinding return interestingPart.LastIndexOf("