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..62bb433407 100644
--- a/src/AddIns/BackendBindings/XamlBinding/XamlBinding.Tests/UtilsTests.cs
+++ b/src/AddIns/BackendBindings/XamlBinding/XamlBinding.Tests/UtilsTests.cs
@@ -18,85 +18,134 @@ namespace ICSharpCode.XamlBinding.Tests
public class UtilsTests
{
[Test]
- public void XmlNamespacesForOffsetSimple()
+ public void DiffTestSimple()
{
- string xaml = File.ReadAllText("Test1.xaml");
- int offset = xaml.IndexOf("CheckBox") + "CheckBox ".Length;
+ string xaml = "";
+ int offset = " {
- {"xmlns", "http://schemas.microsoft.com/netfx/2007/xaml/presentation"},
- {"xmlns:x", "http://schemas.microsoft.com/winfx/2006/xaml"}
- };
+ int actualResult = Utils.GetOffsetFromValueStart(xaml, offset);
- var result = Utils.GetXmlNamespacesForOffset(xaml, offset);
+ Assert.AreEqual(expectedResult, actualResult);
+ }
+
+ [Test]
+ public void DiffTestSimple2()
+ {
+ string xaml = "";
+ int offset = " {
- {"xmlns", "http://schemas.microsoft.com/netfx/2007/xaml/presentation"},
- {"xmlns:x", "http://schemas.microsoft.com/winfx/2006/xaml"},
- {"xmlns:y", "clr-namespace:ICSharpCode.Profiler.Controls;assembly=ICSharpCode.Profiler.Controls"}
- };
+ string text = @"SharpDevelop uses the MSBuild
+libraries for compilation. But when you compile a project
+inside SharpDevelop, there's more going on than a
+simple call to MSBuild.";
- var result = Utils.GetXmlNamespacesForOffset(xaml, offset);
+ int expected = 0;
+ int line = 1;
+ int col = 1;
- foreach (var p in result)
- Debug.Print(p.Key + " " + p.Value);
+ int result = Utils.GetOffsetFromFilePos(text, line, col);
- Assert.AreEqual(expectedResult, result, "Is not equal");
+ Assert.AreEqual(expected, result);
}
[Test]
- public void XmlNamespacesForOffsetComplex()
+ public void GetOffsetTest2()
{
- string xaml = File.ReadAllText("Test3.xaml");
- int offset = xaml.IndexOf("CheckBox") + "CheckBox ".Length;
+ string text = @"SharpDevelop uses the MSBuild
+libraries for compilation. But when you compile a project
+inside SharpDevelop, there's more going on than a
+simple call to MSBuild.";
+
+ int expected = 4;
+ int line = 1;
+ int col = 5;
- var expectedResult = new Dictionary {
- {"xmlns", "http://schemas.microsoft.com/netfx/2007/xaml/presentation"},
- {"xmlns:x", "clr-namespace:ICSharpCode.Profiler.Controls;assembly=ICSharpCode.Profiler.Controls"}
- };
+ int result = Utils.GetOffsetFromFilePos(text, line, col);
+
+ Assert.AreEqual(expected, result);
+ }
+
+ [Test]
+ public void GetOffsetTest3()
+ {
+ string text = @"SharpDevelop uses the MSBuild
+libraries for compilation. But when you compile a project
+inside SharpDevelop, there's more going on than a
+simple call to MSBuild.";
- var result = Utils.GetXmlNamespacesForOffset(xaml, offset);
+ int expected = 0;
+ int line = 0;
+ int col = 5;
- foreach (var p in result)
- Debug.Print(p.Key + " " + p.Value);
+ int result = Utils.GetOffsetFromFilePos(text, line, col);
- Assert.AreEqual(expectedResult, result, "Is not equal");
+ Assert.AreEqual(expected, result);
}
[Test]
- public void DiffTestSimple()
+ public void GetOffsetTest4()
{
- string xaml = "";
- int offset = "";
- int offset = "
- ..\..\..\..\Tools\NUnit\nunit.framework.dll
- False
+ ..\..\..\..\..\bin\Tools\NUnit\nunit.framework.dll
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,37 +33,93 @@ 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";
- public static XamlContext ResolveContext(ITextEditor editor, char typedValue)
+ public static XamlContext ResolveContext(string text, string fileName, int line, int col)
{
- string text = editor.Document.Text;
- int offset = editor.Caret.Offset;
- XamlResolver resolver = new XamlResolver();
+ int offset = Utils.GetOffsetFromFilePos(text, line, col);
- ParseInformation info = ParserService.GetParseInformation(editor.FileName);
+ ParseInformation info = ParserService.GetParseInformation(fileName);
XmlElementPath path = XmlParser.GetActiveElementStartPathAtIndex(text, offset);
string attribute = XmlParser.GetAttributeNameAtIndex(text, offset);
string attributeValue = XmlParser.GetAttributeValueAtIndex(text, offset);
bool inAttributeValue = XmlParser.IsInsideAttributeValue(text, offset);
int offsetFromValueStart = Utils.GetOffsetFromValueStart(text, offset);
- ResolveResult rr = null;
AttributeValue value = null;
- XamlExpressionContext cxt = new XamlExpressionContext(path, attribute, inAttributeValue);
+ value = MarkupExtensionParser.ParseValue(attributeValue);
+
+ XamlContextDescription description = XamlContextDescription.InTag;
+
+ if (path == null || path.Elements.Count == 0) {
+ description = XamlContextDescription.None;
+ path = XmlParser.GetParentElementPath(text.Substring(0, offset));
+ } else {
+ int ltOffset = XmlParser.GetActiveElementStartIndex(text, offset);
+ if (ltOffset == -1)
+ description = XamlContextDescription.AtTag;
+ else {
+ string space = text.Substring(ltOffset + 1, offset - ltOffset - 1);
+ var last = path.Elements.LastOrDefault();
+ if (last != null && last.ToString().StartsWith(space, StringComparison.Ordinal))
+ description = XamlContextDescription.AtTag;
+ }
+ }
+
+ if (inAttributeValue)
+ description = XamlContextDescription.InAttributeValue;
+
+ if (value != null && !value.IsString)
+ description = XamlContextDescription.InMarkupExtension;
+
+ if (Utils.IsInsideXmlComment(text, offset))
+ description = XamlContextDescription.InComment;
+
+ Dictionary xmlnsDefs = new Dictionary();
- if (!string.IsNullOrEmpty(attribute)) {
- rr = resolver.Resolve(new ExpressionResult(attribute, cxt) { Region = new DomRegion(1,1) }, info, text);
+ using (XmlTextReader reader = Utils.CreateReaderAtTarget(text, line, col)) {
+ xmlnsDefs.AddRange(reader.GetNamespacesInScope(XmlNamespaceScope.All));
}
+ var context = new XamlContext() {
+ Description = description,
+ AttributeName = attribute,
+ AttributeValue = value,
+ RawAttributeValue = attributeValue,
+ ValueStartOffset = offsetFromValueStart,
+ Path = (path == null || path.Elements.Count == 0) ? null : path,
+ XmlnsDefinitions = xmlnsDefs,
+ ParseInformation = info
+ };
+
+ return context;
+ }
+
+ public static XamlCompletionContext ResolveCompletionContext(ITextEditor editor, char typedValue)
+ {
+ string text = editor.Document.Text;
+ int offset = editor.Caret.Offset;
+
+ ParseInformation info = ParserService.GetParseInformation(editor.FileName);
+ XmlElementPath path = XmlParser.GetActiveElementStartPathAtIndex(text, offset);
+ string attribute = XmlParser.GetAttributeNameAtIndex(text, offset);
+ string attributeValue = XmlParser.GetAttributeValueAtIndex(text, offset);
+ bool inAttributeValue = XmlParser.IsInsideAttributeValue(text, offset);
+ int offsetFromValueStart = Utils.GetOffsetFromValueStart(text, offset);
+ AttributeValue value = null;
+
value = MarkupExtensionParser.ParseValue(attributeValue);
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 +128,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;
}
}
@@ -85,47 +142,116 @@ namespace ICSharpCode.XamlBinding
if (Utils.IsInsideXmlComment(text, offset))
description = XamlContextDescription.InComment;
- var context = new XamlContext() {
+ Dictionary xmlnsDefs = new Dictionary();
+
+ using (XmlTextReader reader = Utils.CreateReaderAtTarget(text, editor.Caret.Line, editor.Caret.Column)) {
+ xmlnsDefs.AddRange(reader.GetNamespacesInScope(XmlNamespaceScope.All));
+ }
+
+ var context = new XamlCompletionContext() {
PressedKey = typedValue,
Description = description,
- ResolvedExpression = rr,
AttributeName = attribute,
AttributeValue = value,
RawAttributeValue = attributeValue,
ValueStartOffset = offsetFromValueStart,
- Path = (path == null || path.Elements.Count == 0) ? null : path
+ Path = (path == null || path.Elements.Count == 0) ? null : path,
+ XmlnsDefinitions = xmlnsDefs,
+ ParseInformation = info,
+ Editor = editor
};
- LoggingService.Debug(context);
-
return context;
}
- static List CreateListForAttributeName(ParseInformation parseInfo, XamlExpressionContext context, string[] existingItems)
+ static List CreateListForAttributeName(XamlCompletionContext context, string[] existingItems)
{
- if (context.ElementPath.Elements.Count == 0)
- return null;
- QualifiedName lastElement = context.ElementPath.Elements[context.ElementPath.Elements.Count - 1];
- XamlCompilationUnit cu = parseInfo.BestCompilationUnit as XamlCompilationUnit;
+ QualifiedName lastElement = context.Path.Elements.LastOrDefault();
+ XamlCompilationUnit cu = context.ParseInformation.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(context);
+
+ 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 +262,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,48 +282,61 @@ 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();
}
- public static ICompletionItemList CreateListForContext(ITextEditor editor, XamlContext context)
+ public static ICompletionItemList CreateListForContext(ITextEditor editor, XamlCompletionContext context)
{
XamlCompletionItemList list = new XamlCompletionItemList();
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 loc = editor.Document.OffsetToPosition(Utils.GetParentElementStart(editor));
+ var existing = Utils.GetListOfExistingAttributeNames(editor.Document.Text, loc.Line, loc.Column);
+ list.Items.AddRange(CreateListForAttributeName(context, 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.Line, editor.Caret.Column);
+ list.Items.AddRange(CreateListForAttributeName(context, existingAttribs));
QualifiedName last = context.Path.Elements[context.Path.Elements.Count - 1];
- TypeResolveResult trr = new XamlResolver().Resolve(new ExpressionResult(last.Name, new XamlExpressionContext(context.Path, null, false)), info, editor.Document.Text) as TypeResolveResult;
+ TypeResolveResult trr = new XamlResolver().Resolve(new ExpressionResult(last.Name, context), info, editor.Document.Text) as TypeResolveResult;
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,10 +349,24 @@ namespace ICSharpCode.XamlBinding
return list;
}
- public static IEnumerable CreateMarkupExtensionInsight(XamlContext context, ParseInformation info, ITextEditor editor)
+ 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(XamlCompletionContext context, ParseInformation info, ITextEditor editor)
{
- var markup = GetInnermostMarkup(context.AttributeValue.ExtensionValue);
- var trr = ResolveMarkupExtensionType(markup, info, editor, context.Path);
+ var markup = Utils.GetInnermostMarkup(context.AttributeValue.ExtensionValue);
+ var trr = ResolveMarkupExtensionType(markup, context);
if (trr != null) {
var ctors = trr.ResolvedType
@@ -228,14 +381,14 @@ namespace ICSharpCode.XamlBinding
}
}
- public static ICompletionItemList CreateMarkupExtensionCompletion(XamlContext context, ParseInformation info, ITextEditor editor)
+ public static ICompletionItemList CreateMarkupExtensionCompletion(XamlCompletionContext context, ParseInformation info, ITextEditor editor)
{
var list = new XamlCompletionItemList();
var path = XmlParser.GetActiveElementStartPathAtIndex(editor.Document.Text, editor.Caret.Offset);
- var markup = GetInnermostMarkup(context.AttributeValue.ExtensionValue);
+ var markup = Utils.GetInnermostMarkup(context.AttributeValue.ExtensionValue);
- var trr = ResolveMarkupExtensionType(markup, info, editor, path);
+ var trr = ResolveMarkupExtensionType(markup, context);
if (trr == null) {
list.Items.AddRange(CreateListOfMarkupExtensions(info, editor.Document.Text, editor.Caret.Line, editor.Caret.Column));
@@ -259,11 +412,11 @@ 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().Where(p => p.CanSet && p.IsPublic).Select(p => new XamlCodeCompletionItem(p, p.Name + "=")).Cast());
}
}
- static void DoPositionalArgsCompletion(XamlCompletionItemList list, XamlContext context, TypeResolveResult trr, ParseInformation info, ITextEditor editor)
+ static void DoPositionalArgsCompletion(XamlCompletionItemList list, XamlCompletionContext context, TypeResolveResult trr, ParseInformation info, ITextEditor editor)
{
switch (trr.ResolvedType.FullyQualifiedName) {
case "System.Windows.Markup.ArrayExtension":
@@ -272,12 +425,12 @@ namespace ICSharpCode.XamlBinding
break;
case "System.Windows.Markup.StaticExtension":
if (context.AttributeValue.ExtensionValue.PositionalArguments.Count == 1 && context.PressedKey == ' ') break;
- if (context.AttributeValue.ExtensionValue.PositionalArguments.Count <= 1) DoStaticExtensionCompletion(list, context, info, editor);
+ if (context.AttributeValue.ExtensionValue.PositionalArguments.Count <= 1) DoStaticExtensionCompletion(list, context);
break;
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;
@@ -318,7 +471,7 @@ namespace ICSharpCode.XamlBinding
}
}
- public static IEnumerable MemberCompletion(ITextEditor editor, IReturnType type)
+ public static IEnumerable MemberCompletion(XamlCompletionContext context, IReturnType type)
{
if (type == null || type.GetUnderlyingClass() == null)
yield break;
@@ -328,7 +481,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") {
@@ -339,60 +492,79 @@ namespace ICSharpCode.XamlBinding
case ClassType.Delegate:
IMethod invoker = c.Methods.Where(method => method.Name == "Invoke").FirstOrDefault();
if (invoker != null) {
- var path = XmlParser.GetActiveElementStartPathAtIndex(editor.Document.Text, editor.Caret.Offset);
- 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)
+ if (context.Path != null) {
+ var item = context.Path.Elements.LastOrDefault();
+ var evt = ResolveAttribute(context.AttributeName, context) as IEvent;
+ if (evt == null)
+ break;
+
+ int offset = XmlParser.GetActiveElementStartIndex(context.Editor.Document.Text, context.Editor.Caret.Offset);
+
+ if (offset == -1)
break;
- string name = Utils.GetAttributeValue(editor.Document.Text, editor.Caret.Offset, "name");
- yield return new NewEventCompletionItem(e, (string.IsNullOrEmpty(name)) ? item.Name : name);
- foreach (var eventItem in CompletionDataHelper.AddMatchingEventHandlers(editor, invoker))
+ var loc = context.Editor.Document.OffsetToPosition(offset);
+
+ string prefix = Utils.GetXamlNamespacePrefix(context);
+ string name = Utils.GetAttributeValue(context.Editor.Document.Text, loc.Line, loc.Column + 1, "name");
+ if (string.IsNullOrEmpty(name))
+ name = Utils.GetAttributeValue(context.Editor.Document.Text, loc.Line, loc.Column + 1, (string.IsNullOrEmpty(prefix) ? "" : prefix + ":") + "name");
+
+ yield return new NewEventCompletionItem(evt, (string.IsNullOrEmpty(name)) ? item.Name : name);
+
+ foreach (var eventItem in CompletionDataHelper.AddMatchingEventHandlers(context.Editor, invoker))
yield return eventItem;
}
}
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)
+ static IEntity ResolveAttribute(string attribute, XamlCompletionContext context)
{
XamlResolver resolver = new XamlResolver();
-
- var path = XmlParser.GetActiveElementStartPathAtIndex(editor.Document.Text, editor.Caret.Offset);
- var exp = new ExpressionResult(attribute, new XamlExpressionContext(path, attribute, false));
- var info = ParserService.GetParseInformation(editor.FileName);
-
- var mrr = resolver.Resolve(exp, info, editor.Document.Text) as MemberResolveResult;
+ var exp = new ExpressionResult(attribute, context);
+ var mrr = resolver.Resolve(exp, context.ParseInformation, context.Editor.Document.Text) as MemberResolveResult;
return mrr.ResolvedMember;
}
- static void DoStaticExtensionCompletion(XamlCompletionItemList list, XamlContext context, ParseInformation info, ITextEditor editor)
+ static void DoStaticExtensionCompletion(XamlCompletionItemList list, XamlCompletionContext context)
{
AttributeValue selItem = context.AttributeValue.ExtensionValue.PositionalArguments.LastOrDefault();
if (context.PressedKey == '.') {
if (selItem != null && selItem.IsString) {
- var rr = ResolveStringValue(selItem.StringValue, context.Path, info, editor) as TypeResolveResult;
+ var rr = ResolveStringValue(selItem.StringValue, context) as TypeResolveResult;
if (rr != null)
- list.Items.AddRange(MemberCompletion(editor, rr.ResolvedType));
+ list.Items.AddRange(MemberCompletion(context, rr.ResolvedType));
}
} else {
if (selItem != null && selItem.IsString) {
int index = selItem.StringValue.IndexOf('.');
string s = (index > -1) ? selItem.StringValue.Substring(0, index) : selItem.StringValue;
- var rr = ResolveStringValue(s, context.Path, info, editor) as TypeResolveResult;
+ var rr = ResolveStringValue(s, context) as TypeResolveResult;
if (rr != null) {
- list.Items.AddRange(MemberCompletion(editor, rr.ResolvedType));
+ list.Items.AddRange(MemberCompletion(context, rr.ResolvedType));
list.PreselectionLength = selItem.StringValue.Length - index - 1;
list.SuggestedItem = list.Items.FirstOrDefault(item => item.Text.StartsWith(selItem.StringValue.Substring(index + 1), StringComparison.OrdinalIgnoreCase));
} else
- DoStaticTypeCompletion(selItem, list, info, editor);
+ DoStaticTypeCompletion(selItem, list, context.ParseInformation, context.Editor);
} else {
- DoStaticTypeCompletion(selItem, list, info, editor);
+ DoStaticTypeCompletion(selItem, list, context.ParseInformation, context.Editor);
}
}
}
@@ -401,7 +573,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;
@@ -410,10 +584,10 @@ namespace ICSharpCode.XamlBinding
}
}
- static ResolveResult ResolveStringValue(string value, XmlElementPath path, ParseInformation info, ITextEditor editor)
+ static ResolveResult ResolveStringValue(string value, XamlCompletionContext context)
{
var resolver = new XamlResolver();
- var rr = resolver.Resolve(new ExpressionResult(value, new XamlExpressionContext(path, string.Empty, false)), info, editor.Document.Text);
+ var rr = resolver.Resolve(new ExpressionResult(value, context), context.ParseInformation, context.Editor.Document.Text);
return rr;
}
@@ -421,33 +595,22 @@ namespace ICSharpCode.XamlBinding
{
return null;
}
-
- public static MarkupExtensionInfo GetInnermostMarkup(MarkupExtensionInfo markup)
- {
- var lastPair = markup.NamedArguments.LastOrDefault();
- var last = markup.PositionalArguments.LastOrDefault();
-
- if (markup.NamedArguments.Count > 0)
- last = lastPair.Value;
-
- if (last != null) {
- if (!last.IsString) {
- return GetInnermostMarkup(last.ExtensionValue);
- }
- }
-
- return markup;
- }
- static TypeResolveResult ResolveMarkupExtensionType(MarkupExtensionInfo markup, ParseInformation info, ITextEditor editor, XmlElementPath path)
+ public static TypeResolveResult ResolveMarkupExtensionType(MarkupExtensionInfo markup, XamlCompletionContext context)
{
XamlResolver resolver = new XamlResolver();
- TypeResolveResult trr = resolver.Resolve(new ExpressionResult(markup.ExtensionType, new XamlExpressionContext(path, null, false)), info, editor.Document.Text) as TypeResolveResult;
- if (trr == null) trr = resolver.Resolve(new ExpressionResult(markup.ExtensionType + "Extension", new XamlExpressionContext(path, null, false)), info, editor.Document.Text) as TypeResolveResult;
+ TypeResolveResult trr = resolver.Resolve(new ExpressionResult(markup.ExtensionType, context), context.ParseInformation, context.Editor.Document.Text) as TypeResolveResult;
+ if (trr == null) trr = resolver.Resolve(new ExpressionResult(markup.ExtensionType + "Extension", context), context.ParseInformation, context.Editor.Document.Text) as TypeResolveResult;
return trr;
}
+ public static TypeResolveResult ResolveType(string name, XamlCompletionContext context)
+ {
+ return new XamlResolver()
+ .Resolve(new ExpressionResult(name, context), context.ParseInformation, context.Editor.Document.Text) as TypeResolveResult;
+ }
+
public static IEnumerable AddMatchingEventHandlers(ITextEditor editor, IMethod delegateInvoker)
{
ParseInformation p = ParserService.GetParseInformation(editor.FileName);
@@ -473,7 +636,7 @@ namespace ICSharpCode.XamlBinding
break;
}
if (equal) {
- yield return new XamlCompletionItem(m);
+ yield return new XamlCodeCompletionItem(m);
}
}
}
@@ -491,15 +654,22 @@ namespace ICSharpCode.XamlBinding
return result;
}
- static IDictionary> GetClassesFromContext(ParseInformation parseInfo, string fileContent, int caretLine, int caretColumn)
+ 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 = Utils.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 = Utils.CreateReaderAtTarget(fileContent, caretLine, caretColumn)) {
IProjectContent pc = parseInfo.BestCompilationUnit.ProjectContent;
var result = new Dictionary>();
@@ -514,15 +684,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 = Utils.CreateReaderAtTarget(fileContent, caretLine, caretColumn)) {
+ List result = new List();
IProjectContent pc = parseInfo.BestCompilationUnit.ProjectContent;
foreach (var ns in r.GetNamespacesInScope(XmlNamespaceScope.ExcludeXml)) {
@@ -561,10 +724,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 +775,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/MarkupExtensionInfo.cs b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/MarkupExtensionInfo.cs
index 2cb3d0502f..41a25a0bc1 100644
--- a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/MarkupExtensionInfo.cs
+++ b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/MarkupExtensionInfo.cs
@@ -20,9 +20,11 @@ namespace ICSharpCode.XamlBinding
public string ExtensionType { get; set; }
public IList PositionalArguments { get; private set; }
public IDictionary NamedArguments { get; private set; }
+
+ public int StartOffset { get; set; }
public MarkupExtensionInfo()
- : this(string.Empty, new List(), new Dictionary())
+ : this(string.Empty, new List(), new Dictionary(StringComparer.OrdinalIgnoreCase))
{
}
@@ -39,6 +41,8 @@ namespace ICSharpCode.XamlBinding
string stringValue;
MarkupExtensionInfo extensionValue;
+ public int StartOffset { get; set; }
+
public bool IsString {
get { return stringValue != null; }
}
diff --git a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/MarkupExtensionParser.cs b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/MarkupExtensionParser.cs
index 5fccb320e7..cb3dc2d3f8 100644
--- a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/MarkupExtensionParser.cs
+++ b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/MarkupExtensionParser.cs
@@ -19,22 +19,28 @@ namespace ICSharpCode.XamlBinding
var tokenizer = new MarkupExtensionTokenizer(text);
string argumentName = null;
+ int namedArgsStart = 0;
var token = tokenizer.NextToken();
while (token.Kind != MarkupExtensionTokenKind.EndOfFile) {
switch (token.Kind) {
case MarkupExtensionTokenKind.TypeName:
info.ExtensionType = token.Value;
+ info.StartOffset = token.StartOffset;
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;
+ namedArgsStart = token.StartOffset;
break;
case MarkupExtensionTokenKind.String:
if (argumentName != null) {
- info.NamedArguments.Add(argumentName, ParseValue(token.Value));
+ info.NamedArguments.Add(argumentName, ParseValue(token.Value, namedArgsStart));
argumentName = null;
} else {
- info.PositionalArguments.Add(ParseValue(token.Value));
+ info.PositionalArguments.Add(ParseValue(token.Value, token.StartOffset));
}
break;
}
@@ -48,14 +54,19 @@ namespace ICSharpCode.XamlBinding
}
public static AttributeValue ParseValue(string text)
+ {
+ return ParseValue(text, 0);
+ }
+
+ public static AttributeValue ParseValue(string text, int offset)
{
if (string.IsNullOrEmpty(text))
- return new AttributeValue(string.Empty);
+ return new AttributeValue(string.Empty) { StartOffset = offset };
if (text.StartsWith("{", StringComparison.OrdinalIgnoreCase))
- return new AttributeValue(Parse(text));
+ return new AttributeValue(Parse(text)) { StartOffset = offset };
else
- return new AttributeValue(text);
+ return new AttributeValue(text) { StartOffset = offset };
}
}
}
diff --git a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/MarkupExtensionToken.cs b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/MarkupExtensionToken.cs
index a5140fb529..97a02b18e7 100644
--- a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/MarkupExtensionToken.cs
+++ b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/MarkupExtensionToken.cs
@@ -14,6 +14,8 @@ namespace ICSharpCode.XamlBinding
public MarkupExtensionTokenKind Kind { get; private set; }
public string Value { get; private set; }
+ public int StartOffset { get; set; }
+
public MarkupExtensionToken(MarkupExtensionTokenKind kind, string value)
{
this.Kind = kind;
diff --git a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/MarkupExtensionTokenizer.cs b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/MarkupExtensionTokenizer.cs
index 1caf874500..ca83d09b45 100644
--- a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/MarkupExtensionTokenizer.cs
+++ b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/MarkupExtensionTokenizer.cs
@@ -27,6 +27,8 @@ namespace ICSharpCode.XamlBinding
string text;
int pos;
+ int startPos;
+
Queue tokens = new Queue();
///
@@ -51,7 +53,7 @@ namespace ICSharpCode.XamlBinding
void AddToken(MarkupExtensionTokenKind kind, string val)
{
- tokens.Enqueue(new MarkupExtensionToken(kind, val));
+ tokens.Enqueue(new MarkupExtensionToken(kind, val) { StartOffset = startPos });
}
void ParseBeginning()
@@ -75,16 +77,20 @@ namespace ICSharpCode.XamlBinding
case '}':
AddToken(MarkupExtensionTokenKind.CloseBrace, "}");
pos++;
+ startPos = pos;
break;
case '=':
AddToken(MarkupExtensionTokenKind.Equals, "=");
pos++;
+ startPos = pos;
break;
case ',':
AddToken(MarkupExtensionTokenKind.Comma, ",");
pos++;
+ startPos = pos;
break;
default:
+ startPos = pos;
MembernameOrString();
break;
}
diff --git a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/Utils.cs b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/Utils.cs
index 20f9f7dc92..6b6e69d520 100644
--- a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/Utils.cs
+++ b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/Utils.cs
@@ -10,9 +10,11 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
+using System.Text.RegularExpressions;
using System.Xml;
using ICSharpCode.Core;
+using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.XmlEditor;
namespace ICSharpCode.XamlBinding
@@ -22,129 +24,40 @@ namespace ICSharpCode.XamlBinding
///
public static class Utils
{
- public static bool HasMatchingEndTag(string tagname, string text, int offset)
+ internal static bool IsReaderAtTarget(XmlTextReader r, int line, int col)
{
- int index = XmlParser.GetActiveElementStartIndex(text, offset);
- if (index == -1)
+ if (r.LineNumber > line)
+ return true;
+ else if (r.LineNumber == line)
+ return r.LinePosition >= col;
+ else
return false;
-
- text = text.Substring(index);
-
- var path = XmlParser.GetActiveElementStartPathAtIndex(text, index);
-
- XmlReader reader = XmlTextReader.Create(new StringReader(text));
- int startTags = 0;
- try {
- while (reader.Read()) {
- switch (reader.NodeType) {
- case XmlNodeType.Element:
- if (!reader.IsEmptyElement)
- startTags++;
- break;
- case XmlNodeType.EndElement:
- startTags--;
- if (startTags == 0 && tagname == reader.Name) {
- return true;
- }
- break;
- }
- }
- } catch (XmlException e) {
- Debug.Print(e.ToString());
- return false;
- }
-
- return false;
}
- public static string GetAttributeValue(string text, int offset, string name)
+ public static string GetAttributeValue(string text, int line, int col, string name)
{
- text = SimplifyToSingleElement(text, offset, "Test");
-
- if (text == null)
- return null;
-
- XmlReader reader = XmlTextReader.Create(new StringReader(text));
-
- try {
- reader.ReadToFollowing("Test");
+ try {
+ XmlTextReader reader = new XmlTextReader(new StringReader(text));
+ reader.XmlResolver = null;
+ while (reader.Read() && !IsReaderAtTarget(reader, line, col)) { }
+
+
if (!reader.MoveToFirstAttribute())
return null;
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) { }
-
- return null;
- }
-
- public static Dictionary GetXmlNamespacesForOffset(string fileContent, int offset)
- {
- if (fileContent == null)
- throw new ArgumentNullException("fileContent");
- if (offset < 0 || offset > fileContent.Length)
- throw new ArgumentOutOfRangeException("offset", offset, "Value must be between 0 and " + fileContent.Length);
-
- var map = new Dictionary();
-
- int endIndex = fileContent.IndexOfAny(new char[] {'<', '>'}, offset);
- if (endIndex > -1)
- fileContent = fileContent.Substring(0, endIndex + 1);
-
- int lastWhiteSpacePos = fileContent.LastIndexOfAny(new char[] {' ', '\t', '\n', '\r'});
-
- bool inDouble = false, inSingle = false;
-
- for (int i = 0; i < fileContent.Length; i++) {
- if (fileContent[i] == '"' && !inSingle)
- inDouble = !inDouble;
- if (fileContent[i] == '\'' && !inDouble)
- inSingle = !inSingle;
- if (fileContent[i] == '>') {
- int lastDelimiterPos = fileContent.Substring(0, i + 1).LastIndexOfAny(new char[] {'>', '/'});
- if (inDouble) {
- fileContent.Insert(lastDelimiterPos, "\"");
- i++;
- inDouble = false;
- }
- if (inSingle) {
- fileContent.Insert(lastDelimiterPos, "'");
- inSingle = false;
- i++;
- }
- }
- }
-
- fileContent = fileContent.Replace("", " ").Replace("?>", " ").Replace("<", " ").Replace("/>", " ").Replace(">", " ").Replace("\n", " ").Replace("\r", " ").Replace("\t", " ");
- while (fileContent.Contains(" "))
- fileContent = fileContent.Replace(" ", " ");
-
- fileContent = fileContent.Replace("= \"", "=\"");
- fileContent = fileContent.Replace(" =\"", "=\"");
-
- Debug.Print(fileContent);
-
- string[] data = fileContent.Split(' ');
-
- var filter1 = data.Where(s => s.StartsWith("xmlns"));
-
- foreach (string item in filter1) {
- string[] parts = item.Split(new char[] {'='}, 2);
- if (parts.Length == 2) {
- if (map.ContainsKey(parts[0])) // replace namespace with new one
- map.Remove(parts[0]);
- map.Add(parts[0], parts[1].Trim('"', '\''));
- }
+ } catch (XmlException e) {
+ Debug.Print(e.ToString());
}
- return map;
+ return null;
}
public static int GetOffsetFromValueStart(string xaml, int offset)
@@ -162,28 +75,29 @@ namespace ICSharpCode.XamlBinding
return offset - start - 1;
}
- public static string[] GetListOfExistingAttributeNames(string text, int offset)
+ public static string[] GetListOfExistingAttributeNames(string text, int line, int col)
{
List list = new List();
- text = SimplifyToSingleElement(text, offset, "Test");
-
if (text == null)
return list.ToArray();
- XmlReader reader = XmlTextReader.Create(new StringReader(text));
+ using (XmlReader reader = CreateReaderAtTarget(text, line, col)) {
+ try {
+ if (!reader.MoveToFirstAttribute())
+ return list.ToArray();
+
+ do {
+ LoggingService.Debug("name: " + reader.Name + " value: " + reader.Value);
+ list.Add(reader.Name);
+ } while (reader.MoveToNextAttribute());
+ } catch (XmlException e) {
+ Debug.Print(e.ToString());
+ }
+ }
- try {
- reader.ReadToFollowing("Test");
-
- if (!reader.MoveToFirstAttribute())
- return list.ToArray();
-
- do {
- LoggingService.Debug("name: " + reader.Name + " value: " + reader.Value);
- list.Add(reader.Name);
- } while (reader.MoveToNextAttribute());
- } catch (XmlException) { }
+ foreach (var item in list)
+ Debug.Print(item);
return list.ToArray();
}
@@ -203,30 +117,15 @@ namespace ICSharpCode.XamlBinding
return startIndex;
}
-
- static string SimplifyToSingleElement(string text, int offset, string name)
- {
- int index = XmlParser.GetActiveElementStartIndex(text, offset);
- if (index == -1) return null;
- index = text.IndexOf(' ', 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 + " />";
-
- return text;
- }
- public static string GetXamlNamespacePrefix(string xaml, int offset)
+ static char[] whitespace = new char[] {' ', '\t', '\n', '\r'};
+
+ public static string GetXamlNamespacePrefix(XamlContext context)
{
- var list = Utils.GetXmlNamespacesForOffset(xaml, offset);
- var item = list.FirstOrDefault(i => i.Value == CompletionDataHelper.XamlNamespace);
-
- if (item.Key.StartsWith("xmlns:", StringComparison.OrdinalIgnoreCase))
- return item.Key.Substring("xmlns:".Length);
+ var item = context.XmlnsDefinitions.FirstOrDefault(i => i.Value == CompletionDataHelper.XamlNamespace);
+
+ if (item.Key != null)
+ return item.Key;
return string.Empty;
}
@@ -237,7 +136,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 +146,113 @@ namespace ICSharpCode.XamlBinding
return interestingPart.LastIndexOf("