Browse Source

implemented new XAML code completion features

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@4330 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Siegfried Pammer 17 years ago
parent
commit
d1dd93073d
  1. 216
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/CompletionDataHelper.cs
  2. 2
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/MarkupExtensionInfo.cs
  3. 11
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/MarkupExtensionParser.cs
  4. 10
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/MarkupExtensionTokenizer.cs
  5. 12
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/Options/CodeCompletion.xaml
  6. 32
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/Options/CodeCompletion.xaml.cs
  7. 17
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/Options/XamlBindingOptions.cs
  8. 64
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/Utils.cs
  9. 8
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlBinding.addin
  10. 28
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlBinding.csproj
  11. 116
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlCodeCompletionBinding.cs
  12. 28
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlCompletionItemList.cs
  13. 14
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlContext.cs
  14. 123
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlResolver.cs

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

@ -51,38 +51,38 @@ namespace ICSharpCode.XamlBinding @@ -51,38 +51,38 @@ namespace ICSharpCode.XamlBinding
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;
int elementStartIndex = XmlParser.GetActiveElementStartIndex(text, offset);
AttributeValue value = MarkupExtensionParser.ParseValue(attributeValue);
XamlContextDescription description = XamlContextDescription.None;
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;
}
description = XamlContextDescription.AtTag;
}
if (inAttributeValue)
description = XamlContextDescription.InAttributeValue;
if (text[offset] == '>')
description = XamlContextDescription.None;
if (value != null && !value.IsString)
description = XamlContextDescription.InMarkupExtension;
if (!string.IsNullOrEmpty(attribute) || (elementStartIndex > -1 && offset > 0 && char.IsWhiteSpace(text[offset - 1])))
description = XamlContextDescription.InTag;
if (inAttributeValue) {
description = XamlContextDescription.InAttributeValue;
if (value != null && !value.IsString)
description = XamlContextDescription.InMarkupExtension;
if (attributeValue.StartsWith("{}") && attributeValue.Length > 2)
description = XamlContextDescription.InAttributeValue;
}
if (Utils.IsInsideXmlComment(text, offset))
description = XamlContextDescription.InComment;
Dictionary<string, string> xmlnsDefs = new Dictionary<string, string>();
// TODO : does not work when trying to resolve </Element>, if xmlns declarartion is in <Element>
using (XmlTextReader reader = Utils.CreateReaderAtTarget(text, line, col)) {
xmlnsDefs.AddRange(reader.GetNamespacesInScope(XmlNamespaceScope.All));
}
@ -98,66 +98,15 @@ namespace ICSharpCode.XamlBinding @@ -98,66 +98,15 @@ namespace ICSharpCode.XamlBinding
ParseInformation = info
};
LoggingService.Debug(context);
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.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<string, string> xmlnsDefs = new Dictionary<string, string>();
using (XmlTextReader reader = Utils.CreateReaderAtTarget(text, editor.Caret.Line, editor.Caret.Column)) {
xmlnsDefs.AddRange(reader.GetNamespacesInScope(XmlNamespaceScope.All));
}
var context = new XamlCompletionContext() {
var context = new XamlCompletionContext(ResolveContext(editor.Document.Text, editor.FileName, editor.Caret.Line, editor.Caret.Column)) {
PressedKey = typedValue,
Description = description,
AttributeName = attribute,
AttributeValue = value,
RawAttributeValue = attributeValue,
ValueStartOffset = offsetFromValueStart,
Path = (path == null || path.Elements.Count == 0) ? null : path,
XmlnsDefinitions = xmlnsDefs,
ParseInformation = info,
Editor = editor
};
@ -208,8 +157,12 @@ namespace ICSharpCode.XamlBinding @@ -208,8 +157,12 @@ namespace ICSharpCode.XamlBinding
}
foreach (string @namespace in content.NamespaceNames) {
if (!string.IsNullOrEmpty(@namespace))
list.Add(new XmlnsCompletionItem(@namespace, content.AssemblyName));
if (!string.IsNullOrEmpty(@namespace)) {
if (string.IsNullOrEmpty(content.AssemblyName))
list.Add(new XmlnsCompletionItem(@namespace, false));
else
list.Add(new XmlnsCompletionItem(@namespace, content.AssemblyName));
}
}
}
@ -314,13 +267,14 @@ namespace ICSharpCode.XamlBinding @@ -314,13 +267,14 @@ namespace ICSharpCode.XamlBinding
}
break;
case XamlContextDescription.AtTag:
list.Items.AddRange(standardElements);
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
} else {
list.Items.AddRange(standardElements);
list.Items.AddRange(CreateListForElement(info, editor.Document.Text, editor.Caret.Line, editor.Caret.Column, false));
}
break;
case XamlContextDescription.InTag:
var existingAttribs = Utils.GetListOfExistingAttributeNames(editor.Document.Text, editor.Caret.Line, editor.Caret.Column);
@ -363,9 +317,9 @@ namespace ICSharpCode.XamlBinding @@ -363,9 +317,9 @@ namespace ICSharpCode.XamlBinding
return false;
}
public static IEnumerable<IInsightItem> CreateMarkupExtensionInsight(XamlCompletionContext context, ParseInformation info, ITextEditor editor)
public static IEnumerable<IInsightItem> CreateMarkupExtensionInsight(XamlCompletionContext context)
{
var markup = Utils.GetInnermostMarkup(context.AttributeValue.ExtensionValue);
var markup = Utils.GetMarkupExtensionAtPosition(context.AttributeValue.ExtensionValue, context.Editor.Caret.Offset);
var trr = ResolveMarkupExtensionType(markup, context);
if (trr != null) {
@ -381,23 +335,21 @@ namespace ICSharpCode.XamlBinding @@ -381,23 +335,21 @@ namespace ICSharpCode.XamlBinding
}
}
public static ICompletionItemList CreateMarkupExtensionCompletion(XamlCompletionContext context, ParseInformation info, ITextEditor editor)
public static ICompletionItemList CreateMarkupExtensionCompletion(XamlCompletionContext context)
{
var list = new XamlCompletionItemList();
var path = XmlParser.GetActiveElementStartPathAtIndex(editor.Document.Text, editor.Caret.Offset);
var markup = Utils.GetInnermostMarkup(context.AttributeValue.ExtensionValue);
var path = XmlParser.GetActiveElementStartPathAtIndex(context.Editor.Document.Text, context.Editor.Caret.Offset);
var markup = Utils.GetMarkupExtensionAtPosition(context.AttributeValue.ExtensionValue, context.Editor.Caret.Offset);
var trr = ResolveMarkupExtensionType(markup, context);
if (trr == null) {
list.Items.AddRange(CreateListOfMarkupExtensions(info, editor.Document.Text, editor.Caret.Line, editor.Caret.Column));
list.Items.AddRange(CreateListOfMarkupExtensions(context.ParseInformation, context.Editor.Document.Text, context.Editor.Caret.Line, context.Editor.Caret.Column));
list.PreselectionLength = markup.ExtensionType.Length;
} else {
if (trr.ResolvedType != null) {
if (markup.NamedArguments.Count == 0) {
DoPositionalArgsCompletion(list, context, trr, info, editor);
DoNamedArgsCompletion(list, trr, markup);
if (DoPositionalArgsCompletion(list, context, trr, context.ParseInformation, context.Editor))
DoNamedArgsCompletion(list, trr, markup);
} else
DoNamedArgsCompletion(list, trr, markup);
}
@ -416,7 +368,8 @@ namespace ICSharpCode.XamlBinding @@ -416,7 +368,8 @@ namespace ICSharpCode.XamlBinding
}
}
static void DoPositionalArgsCompletion(XamlCompletionItemList list, XamlCompletionContext context, TypeResolveResult trr, ParseInformation info, ITextEditor editor)
/// <remarks>returns true if elements from named args completion should be added afterwards.</remarks>
static bool DoPositionalArgsCompletion(XamlCompletionItemList list, XamlCompletionContext context, TypeResolveResult trr, ParseInformation info, ITextEditor editor)
{
switch (trr.ResolvedType.FullyQualifiedName) {
case "System.Windows.Markup.ArrayExtension":
@ -424,21 +377,17 @@ namespace ICSharpCode.XamlBinding @@ -424,21 +377,17 @@ namespace ICSharpCode.XamlBinding
// x:Null/x:Array does not need completion, ignore it
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);
if (context.AttributeValue.ExtensionValue.PositionalArguments.Count <= 1)
return 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, false));
AttributeValue selItem = context.AttributeValue.ExtensionValue.PositionalArguments.LastOrDefault();
if (selItem != null && selItem.IsString) {
string s = selItem.StringValue;
list.PreselectionLength = s.Length;
list.SuggestedItem = list.Items.FirstOrDefault(item => item.Text.StartsWith(s, StringComparison.OrdinalIgnoreCase));
list.PreselectionLength = selItem.StringValue.Length;
}
}
break;
default:
// var ctors = trr.ResolvedType
@ -449,6 +398,8 @@ namespace ICSharpCode.XamlBinding @@ -449,6 +398,8 @@ namespace ICSharpCode.XamlBinding
// //var ctor = FindCompletableCtor(ctors, markup.PositionalArguments.Count)
break;
}
return true;
}
public static IEnumerable<IInsightItem> MemberInsight(MemberResolveResult result)
@ -471,7 +422,7 @@ namespace ICSharpCode.XamlBinding @@ -471,7 +422,7 @@ namespace ICSharpCode.XamlBinding
}
}
public static IEnumerable<ICompletionItem> MemberCompletion(XamlCompletionContext context, IReturnType type)
public static IEnumerable<ICompletionItem> MemberCompletion(XamlCompletionContext context, IReturnType type, string textPrefix)
{
if (type == null || type.GetUnderlyingClass() == null)
yield break;
@ -479,9 +430,19 @@ namespace ICSharpCode.XamlBinding @@ -479,9 +430,19 @@ namespace ICSharpCode.XamlBinding
var c = type.GetUnderlyingClass();
switch (c.ClassType) {
case ClassType.Class:
if (context.Description == XamlContextDescription.InMarkupExtension) {
foreach (IField f in c.Fields)
yield return new XamlCodeCompletionItem(f, textPrefix + f.Name);
foreach (IProperty p in c.Properties.Where(pr => pr.IsPublic && pr.IsStatic && pr.CanGet))
yield return new XamlCodeCompletionItem(p, textPrefix + p.Name);
}
break;
case ClassType.Enum:
foreach (IField f in c.Fields)
yield return new XamlCodeCompletionItem(f);
yield return new XamlCodeCompletionItem(f, textPrefix + f.Name);
foreach (IProperty p in c.Properties.Where(pr => pr.IsPublic && pr.IsStatic && pr.CanGet))
yield return new XamlCodeCompletionItem(p, textPrefix + p.Name);
break;
case ClassType.Struct:
if (c.FullyQualifiedName == "System.Boolean") {
@ -519,17 +480,14 @@ namespace ICSharpCode.XamlBinding @@ -519,17 +480,14 @@ 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;
var classes = c.ProjectContent.Classes.Where(
cla => (cla.FullyQualifiedName == c.FullyQualifiedName + "s" ||
cla.FullyQualifiedName == c.FullyQualifiedName + "es"));
foreach (var coll in classes) {
foreach (var item in coll.Properties)
yield return new DefaultCompletionItem(item.Name);
foreach (var item in coll.Fields.Where(f => f.IsPublic && f.IsStatic && f.ReturnType.FullyQualifiedName == c.FullyQualifiedName))
yield return new DefaultCompletionItem(item.Name);
}
}
@ -542,14 +500,15 @@ namespace ICSharpCode.XamlBinding @@ -542,14 +500,15 @@ namespace ICSharpCode.XamlBinding
return mrr.ResolvedMember;
}
static void DoStaticExtensionCompletion(XamlCompletionItemList list, XamlCompletionContext context)
static bool 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) as TypeResolveResult;
if (rr != null)
list.Items.AddRange(MemberCompletion(context, rr.ResolvedType));
list.Items.AddRange(MemberCompletion(context, rr.ResolvedType, string.Empty));
return false;
}
} else {
if (selItem != null && selItem.IsString) {
@ -557,16 +516,19 @@ namespace ICSharpCode.XamlBinding @@ -557,16 +516,19 @@ namespace ICSharpCode.XamlBinding
string s = (index > -1) ? selItem.StringValue.Substring(0, index) : selItem.StringValue;
var rr = ResolveStringValue(s, context) as TypeResolveResult;
if (rr != null) {
list.Items.AddRange(MemberCompletion(context, rr.ResolvedType));
list.Items.AddRange(MemberCompletion(context, rr.ResolvedType, (index == -1) ? "." : string.Empty));
list.PreselectionLength = (index > -1) ? selItem.StringValue.Length - index - 1 : 0;
list.PreselectionLength = selItem.StringValue.Length - index - 1;
list.SuggestedItem = list.Items.FirstOrDefault(item => item.Text.StartsWith(selItem.StringValue.Substring(index + 1), StringComparison.OrdinalIgnoreCase));
return false;
} else
DoStaticTypeCompletion(selItem, list, context.ParseInformation, context.Editor);
} else {
DoStaticTypeCompletion(selItem, list, context.ParseInformation, context.Editor);
}
}
return true;
}
static void DoStaticTypeCompletion(AttributeValue selItem, XamlCompletionItemList list, ParseInformation info, ITextEditor editor)
@ -578,9 +540,7 @@ namespace ICSharpCode.XamlBinding @@ -578,9 +540,7 @@ namespace ICSharpCode.XamlBinding
.Cast<ICompletionItem>());
}
if (selItem != null && selItem.IsString) {
string s = selItem.StringValue;
list.PreselectionLength = s.Length;
list.SuggestedItem = list.Items.FirstOrDefault(item => item.Text.StartsWith(s, StringComparison.OrdinalIgnoreCase));
list.PreselectionLength = selItem.StringValue.Length;
}
}
@ -599,16 +559,32 @@ namespace ICSharpCode.XamlBinding @@ -599,16 +559,32 @@ namespace ICSharpCode.XamlBinding
public static TypeResolveResult ResolveMarkupExtensionType(MarkupExtensionInfo markup, XamlCompletionContext context)
{
XamlResolver resolver = new XamlResolver();
XamlContextDescription desc = context.Description;
context.Description = XamlContextDescription.AtTag;
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;
context.Description = desc;
return trr;
}
public static TypeResolveResult ResolveType(string name, XamlCompletionContext context)
public static IReturnType ResolveType(string name, XamlCompletionContext context)
{
return new XamlResolver()
.Resolve(new ExpressionResult(name, context), context.ParseInformation, context.Editor.Document.Text) as TypeResolveResult;
XamlCompilationUnit cu = context.ParseInformation.BestCompilationUnit as XamlCompilationUnit;
if (cu == null)
return null;
string prefix = "";
int len = name.IndexOf(':');
if (len > 0) {
prefix = name.Substring(0, len);
name = name.Substring(len + 1, name.Length - len - 1);
}
string namespaceName = "";
if (context.XmlnsDefinitions.TryGetValue(prefix, out namespaceName)) {
IReturnType rt = cu.CreateType(namespaceName, name);
if (rt != null)
return rt;
}
return null;
}
public static IEnumerable<ICompletionItem> AddMatchingEventHandlers(ITextEditor editor, IMethod delegateInvoker)

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

@ -22,7 +22,7 @@ namespace ICSharpCode.XamlBinding @@ -22,7 +22,7 @@ namespace ICSharpCode.XamlBinding
public IDictionary<string, AttributeValue> NamedArguments { get; private set; }
public int StartOffset { get; set; }
public MarkupExtensionInfo()
: this(string.Empty, new List<AttributeValue>(), new Dictionary<string, AttributeValue>(StringComparer.OrdinalIgnoreCase))
{

11
src/AddIns/BackendBindings/XamlBinding/XamlBinding/MarkupExtensionParser.cs

@ -31,13 +31,13 @@ namespace ICSharpCode.XamlBinding @@ -31,13 +31,13 @@ namespace ICSharpCode.XamlBinding
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));
info.TryAddNamedArgument(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, namedArgsStart));
info.TryAddNamedArgument(argumentName, ParseValue(token.Value, namedArgsStart));
argumentName = null;
} else {
info.PositionalArguments.Add(ParseValue(token.Value, token.StartOffset));
@ -53,6 +53,13 @@ namespace ICSharpCode.XamlBinding @@ -53,6 +53,13 @@ namespace ICSharpCode.XamlBinding
return info;
}
static void TryAddNamedArgument(this MarkupExtensionInfo info, string name, AttributeValue value)
{
if (!info.NamedArguments.ContainsKey(name)) {
info.NamedArguments.Add(name, value);
}
}
public static AttributeValue ParseValue(string text)
{
return ParseValue(text, 0);

10
src/AddIns/BackendBindings/XamlBinding/XamlBinding/MarkupExtensionTokenizer.cs

@ -143,7 +143,15 @@ namespace ICSharpCode.XamlBinding @@ -143,7 +143,15 @@ namespace ICSharpCode.XamlBinding
}
string valueText = b.ToString();
if (pos < text.Length && text[pos] == '=') {
AddToken(MarkupExtensionTokenKind.MemberName, valueText.Trim());
int splitPos = valueText.LastIndexOf(' ');
if (splitPos > -1) {
string valueString = valueText.Substring(0, splitPos).Trim();
string memberString = valueText.Substring(splitPos).Trim();
AddToken(MarkupExtensionTokenKind.String, valueString);
startPos += splitPos;
AddToken(MarkupExtensionTokenKind.MemberName, memberString);
} else
AddToken(MarkupExtensionTokenKind.MemberName, valueText.Trim());
} else {
AddToken(MarkupExtensionTokenKind.String, valueText);
}

12
src/AddIns/BackendBindings/XamlBinding/XamlBinding/Options/CodeCompletion.xaml

@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
<gui:OptionPanel x:Class="ICSharpCode.XamlBinding.Options.CodeCompletion"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:gui="clr-namespace:ICSharpCode.SharpDevelop.Gui;assembly=ICSharpCode.SharpDevelop"
xmlns:sd="http://icsharpcode.net/sharpdevelop/core"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel>
<GroupBox Header="{sd:Localize ICSharpCode.XamlBinding.Options.CodeCompletionGroupLabel}">
<CheckBox Content="{sd:Localize ICSharpCode.XamlBinding.Options.UseExtensionCompletion}"
IsChecked="{sd:OptionBinding ICSharpCode.XamlBinding.Options.XamlBindingOptions.UseExtensionCompletion}" />
</GroupBox>
</StackPanel>
</gui:OptionPanel>

32
src/AddIns/BackendBindings/XamlBinding/XamlBinding/Options/CodeCompletion.xaml.cs

@ -0,0 +1,32 @@ @@ -0,0 +1,32 @@
/*
* Created by SharpDevelop.
* User: Siegfried
* Date: 19.06.2009
* Time: 20:42
*
* To change this template use Tools | Options | Coding | Edit Standard Headers.
*/
using ICSharpCode.SharpDevelop.Gui;
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
namespace ICSharpCode.XamlBinding.Options
{
/// <summary>
/// Interaction logic for CodeCompletion.xaml
/// </summary>
public partial class CodeCompletion : OptionPanel
{
public CodeCompletion()
{
InitializeComponent();
}
}
}

17
src/AddIns/BackendBindings/XamlBinding/XamlBinding/Options/XamlBindingOptions.cs

@ -0,0 +1,17 @@ @@ -0,0 +1,17 @@
/*
* Created by SharpDevelop.
* User: Siegfried
* Date: 19.06.2009
* Time: 22:20
*
* To change this template use Tools | Options | Coding | Edit Standard Headers.
*/
using System;
namespace ICSharpCode.XamlBinding.Options
{
public static class XamlBindingOptions
{
public static bool UseExtensionCompletion { get; set; }
}
}

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

@ -36,16 +36,24 @@ namespace ICSharpCode.XamlBinding @@ -36,16 +36,24 @@ namespace ICSharpCode.XamlBinding
public static string GetAttributeValue(string text, int line, int col, string name)
{
try {
XmlTextReader reader = new XmlTextReader(new StringReader(text));
reader.XmlResolver = null;
try {
XmlReader reader = CreateReaderAtTarget(text, line, col);
while (reader.Read() && !IsReaderAtTarget(reader, line, col)) { }
if (!reader.MoveToFirstAttribute())
return null;
if (!reader.MoveToFirstAttribute()) {
/* int offset = GetOffsetFromFilePos(text, line, col) + 1;
if (XmlParser.IsInsideAttributeValue(text, offset))
text = text.Substring(0, offset) + "\">";
else {
if (!string.IsNullOrEmpty(XmlParser.GetAttributeNameAtIndex(text, offset)))
text = text.Substring(0, offset) + "=\"\">";
else
text = text.Substring(0, offset) + ">";
}
reader = CreateReaderAtTarget(text, line, col);
if (!reader.MoveToFirstAttribute()) */
return null;
}
do {
LoggingService.Debug("name: " + reader.Name + " value: " + reader.Value);
string plainName = reader.Name.ToUpperInvariant();
@ -207,23 +215,6 @@ namespace ICSharpCode.XamlBinding @@ -207,23 +215,6 @@ namespace ICSharpCode.XamlBinding
return r;
}
public static MarkupExtensionInfo GetInnermostMarkup(MarkupExtensionInfo markup)
{
var last = markup.PositionalArguments.LastOrDefault();
if (markup.NamedArguments.Count > 0)
last = markup.NamedArguments.LastOrDefault().Value;
if (last != null) {
if (!last.IsString) {
return GetInnermostMarkup(last.ExtensionValue);
}
}
return markup;
}
/// <summary>
/// Gets the of a markup extension at the given position.
/// </summary>
@ -238,8 +229,6 @@ namespace ICSharpCode.XamlBinding @@ -238,8 +229,6 @@ namespace ICSharpCode.XamlBinding
{
object previous = info.ExtensionType;
Debug.Print("offset: " + offset);
foreach (var item in info.PositionalArguments) {
if (item.StartOffset > offset)
break;
@ -249,10 +238,29 @@ namespace ICSharpCode.XamlBinding @@ -249,10 +238,29 @@ namespace ICSharpCode.XamlBinding
foreach (var pair in info.NamedArguments) {
if (pair.Value.StartOffset > offset)
break;
previous = pair.Value.IsString ? pair.Value : GetMarkupDataAtPosition(pair.Value.ExtensionValue, offset - pair.Value.StartOffset);
previous = pair.Value.IsString ? pair : GetMarkupDataAtPosition(pair.Value.ExtensionValue, offset - pair.Value.StartOffset);
}
return previous;
}
public static MarkupExtensionInfo GetMarkupExtensionAtPosition(MarkupExtensionInfo info, int offset)
{
MarkupExtensionInfo tmp = info;
foreach (var item in info.PositionalArguments) {
if (item.StartOffset > offset)
break;
tmp = item.IsString ? tmp : GetMarkupExtensionAtPosition(item.ExtensionValue, offset - item.StartOffset);
}
foreach (var pair in info.NamedArguments) {
if (pair.Value.StartOffset > offset)
break;
tmp = pair.Value.IsString ? tmp : GetMarkupExtensionAtPosition(pair.Value.ExtensionValue, offset - pair.Value.StartOffset);
}
return tmp;
}
}
}

8
src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlBinding.addin

@ -45,4 +45,12 @@ @@ -45,4 +45,12 @@
<Path name = "/AddIns/DefaultTextEditor/Formatter/XML">
<Class id ="XmlFormatter" class = "ICSharpCode.XmlEditor.XmlFormattingStrategy"/>
</Path>
<!-- Options panel -->
<Path path = "/SharpDevelop/Dialogs/OptionsDialog/TextEditorOptions">
<OptionPanel id = "XamlCompletionPanel"
insertafter = "Markers"
label = "${res:ICSharpCode.XamlBinding.Options.Title}"
class = "ICSharpCode.XamlBinding.Options.CodeCompletion" />
</Path>
</AddIn>

28
src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlBinding.csproj

@ -65,9 +65,17 @@ @@ -65,9 +65,17 @@
<Compile Include="CompletionDataHelper.cs" />
<Compile Include="Extensions.cs" />
<Compile Include="MarkupExtensionTokenizer.cs" />
<Compile Include="MarkupExtensionToken.cs" />
<Compile Include="MarkupExtensionTokenKind.cs" />
<Compile Include="Utils.cs" />
<Compile Include="MarkupExtensionToken.cs">
</Compile>
<Compile Include="MarkupExtensionTokenKind.cs">
</Compile>
<Compile Include="Options\CodeCompletion.xaml.cs">
<DependentUpon>CodeCompletion.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="Options\XamlBindingOptions.cs" />
<Compile Include="Utils.cs">
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="XamlClassReturnType.cs" />
<Compile Include="XamlCodeCompletionBinding.cs" />
@ -82,7 +90,8 @@ @@ -82,7 +90,8 @@
<Compile Include="XamlExpressionFinder.cs">
</Compile>
<Compile Include="XamlColorizer.cs" />
<Compile Include="MarkupExtensionParseException.cs" />
<Compile Include="MarkupExtensionParseException.cs">
</Compile>
<Compile Include="XamlParser.cs" />
<Compile Include="XamlResolver.cs" />
<ProjectReference Include="..\..\..\..\Libraries\ICSharpCode.TextEditor\Project\ICSharpCode.TextEditor.csproj">
@ -105,6 +114,11 @@ @@ -105,6 +114,11 @@
<Name>ICSharpCode.Core</Name>
<Private>False</Private>
</ProjectReference>
<ProjectReference Include="..\..\..\..\Main\ICSharpCode.Core.Presentation\ICSharpCode.Core.Presentation.csproj">
<Project>{7E4A7172-7FF5-48D0-B719-7CD959DD1AC9}</Project>
<Name>ICSharpCode.Core.Presentation</Name>
<Private>False</Private>
</ProjectReference>
<ProjectReference Include="..\..\..\..\Main\ICSharpCode.SharpDevelop.Dom\Project\ICSharpCode.SharpDevelop.Dom.csproj">
<Project>{924EE450-603D-49C1-A8E5-4AFAA31CE6F3}</Project>
<Name>ICSharpCode.SharpDevelop.Dom</Name>
@ -125,4 +139,10 @@ @@ -125,4 +139,10 @@
<Private>False</Private>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Folder Include="Options" />
</ItemGroup>
<ItemGroup>
<Page Include="Options\CodeCompletion.xaml" />
</ItemGroup>
</Project>

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

@ -64,15 +64,14 @@ namespace ICSharpCode.XamlBinding @@ -64,15 +64,14 @@ namespace ICSharpCode.XamlBinding
}
break;
case '{': // starting point for Markup Extension Completion
if (!string.IsNullOrEmpty(context.AttributeName) && XmlParser.IsInsideAttributeValue(editor.Document.Text, editor.Caret.Offset)) {
string valueBeforeCaret = context.RawAttributeValue.Substring(0, context.ValueStartOffset);
if (valueBeforeCaret.StartsWith("{}", StringComparison.OrdinalIgnoreCase))
return CodeCompletionKeyPressResult.None;
if (!string.IsNullOrEmpty(context.AttributeName)
&& XmlParser.IsInsideAttributeValue(editor.Document.Text, editor.Caret.Offset)
&& !(context.RawAttributeValue.StartsWith("{}") && context.RawAttributeValue.Length != 2)
) {
editor.Document.Insert(editor.Caret.Offset, "{}");
editor.Caret.Offset--;
DoMarkupExtensionCompletion(editor, info, CompletionDataHelper.ResolveCompletionContext(editor, '{'));
DoMarkupExtensionCompletion(CompletionDataHelper.ResolveCompletionContext(editor, '{'));
return CodeCompletionKeyPressResult.EatKey;
}
break;
@ -82,6 +81,9 @@ namespace ICSharpCode.XamlBinding @@ -82,6 +81,9 @@ namespace ICSharpCode.XamlBinding
list = CompletionDataHelper.CreateListForContext(editor, context);
editor.ShowCompletionWindow(list);
return CodeCompletionKeyPressResult.Completed;
} else if (context.Description == XamlContextDescription.InMarkupExtension) {
if (DoMarkupExtensionCompletion(context))
return CodeCompletionKeyPressResult.Completed;
}
break;
case ':':
@ -134,10 +136,9 @@ namespace ICSharpCode.XamlBinding @@ -134,10 +136,9 @@ namespace ICSharpCode.XamlBinding
{
XamlCompletionContext context = CompletionDataHelper.ResolveCompletionContext(editor, ' ');
context.Forced = true;
var info = ParserService.GetParseInformation(editor.FileName);
Core.LoggingService.Debug(context);
if (context.Path != null) {
if (!XmlParser.IsInsideAttributeValue(editor.Document.Text, editor.Caret.Offset)) {
if (!XmlParser.IsInsideAttributeValue(editor.Document.Text, editor.Caret.Offset) && context.Description != XamlContextDescription.InAttributeValue) {
var list = CompletionDataHelper.CreateListForContext(editor, context) as XamlCompletionItemList;
string starter = editor.GetWordBeforeCaret().Trim('<', '>');
if (!string.IsNullOrEmpty(starter) && !starter.EndsWith(StringComparison.Ordinal, ' ', '\t', '\n', '\r'))
@ -145,13 +146,9 @@ namespace ICSharpCode.XamlBinding @@ -145,13 +146,9 @@ namespace ICSharpCode.XamlBinding
editor.ShowCompletionWindow(list);
return true;
} else {
// DO NOT USE CompletionDataHelper.CreateListForContext here!!! might result in endless recursion!!!!
// DO NOT USE CompletionDataHelper.CreateListForContext here!!! results in endless recursion!!!!
if (!string.IsNullOrEmpty(context.AttributeName)) {
string valueBeforeCaret = context.RawAttributeValue.Substring(0, context.ValueStartOffset);
if (valueBeforeCaret.StartsWith("{}", StringComparison.OrdinalIgnoreCase))
return false;
if (!DoMarkupExtensionCompletion(editor, info, context)) {
if (!DoMarkupExtensionCompletion(context)) {
XamlResolver resolver = new XamlResolver();
var completionList = new XamlCompletionItemList();
@ -160,51 +157,74 @@ namespace ICSharpCode.XamlBinding @@ -160,51 +157,74 @@ namespace ICSharpCode.XamlBinding
if (mrr != null && mrr.ResolvedType != null) {
var c = mrr.ResolvedType.GetUnderlyingClass();
completionList.Items.AddRange(CompletionDataHelper.MemberCompletion(context, mrr.ResolvedType));
completionList.Items.AddRange(CompletionDataHelper.MemberCompletion(context, mrr.ResolvedType, string.Empty));
editor.ShowInsightWindow(CompletionDataHelper.MemberInsight(mrr));
}
if (context.AttributeName == "Property" && context.Path.Elements.LastOrDefault().Name == "Setter") {
int offset = Utils.GetParentElementStart(editor);
var loc = editor.Document.OffsetToPosition(offset);
string[] attributes = Utils.GetListOfExistingAttributeNames(editor.Document.Text, loc.Line, loc.Column);
if (attributes.Contains("TargetType")) {
AttributeValue value = MarkupExtensionParser.ParseValue(Utils.GetAttributeValue(editor.Document.Text, loc.Line, loc.Column, "TargetType"));
if (!value.IsString) {
TypeResolveResult trr = CompletionDataHelper.ResolveMarkupExtensionType(value.ExtensionValue, context);
var typeName = CompletionDataHelper.ResolveType(GetTypeNameFromTypeExtension(value.ExtensionValue), context);
if (trr != null && trr.ResolvedClass != null && trr.ResolvedClass.FullyQualifiedName == "System.Windows.Markup.TypeExtension"
&& typeName != null && typeName != null) {
completionList.Items.AddRange(
typeName.ResolvedClass.Properties
.Where(p => p.IsPublic && p.CanSet)
.Select(prop => new DefaultCompletionItem(prop.Name))
.Cast<ICompletionItem>()
);
}
}
}
}
if (context.Path.Elements.LastOrDefault().Name == "Setter")
DoSetterCompletion(context, completionList);
completionList.SortItems();
if (context.AttributeName.StartsWith("xmlns"))
completionList.Items.AddRange(CompletionDataHelper.CreateListForXmlnsCompletion(info.BestCompilationUnit.ProjectContent));
completionList.Items.AddRange(CompletionDataHelper.CreateListForXmlnsCompletion(context.ParseInformation.BestCompilationUnit.ProjectContent));
ICompletionListWindow window = editor.ShowCompletionWindow(completionList);
if (context.AttributeName.StartsWith("xmlns"))
window.Width = double.NaN;
return true;
}
return true;
}
}
}
return false;
}
static void DoSetterCompletion(XamlCompletionContext context, XamlCompletionItemList completionList) {
int offset = Utils.GetParentElementStart(context.Editor);
var loc = context.Editor.Document.OffsetToPosition(offset);
AttributeValue value = MarkupExtensionParser.ParseValue(Utils.GetAttributeValue(context.Editor.Document.Text, loc.Line, loc.Column, "TargetType") ?? string.Empty);
if (!value.IsString) {
TypeResolveResult trr = CompletionDataHelper.ResolveMarkupExtensionType(value.ExtensionValue, context);
var typeName = CompletionDataHelper.ResolveType(GetTypeNameFromTypeExtension(value.ExtensionValue), context);
if (trr != null && trr.ResolvedClass != null && trr.ResolvedClass.FullyQualifiedName == "System.Windows.Markup.TypeExtension"
&& typeName != null) {
switch (context.AttributeName) {
case "Value":
var loc2 = context.Editor.Document.OffsetToPosition(XmlParser.GetActiveElementStartIndex(context.Editor.Document.Text, context.Editor.Caret.Offset));
AttributeValue propType = MarkupExtensionParser.ParseValue(
Utils.GetAttributeValue(context.Editor.Document.Text, loc2.Line,
loc2.Column, "Property"));
if (!propType.IsString)
break;
XamlResolver resolver = new XamlResolver();
var member = resolver.Resolve(new ExpressionResult(GetTypeNameFromTypeExtension(value.ExtensionValue) + "." + propType.StringValue, context),
context.ParseInformation, context.Editor.Document.Text) as MemberResolveResult;
if (member == null || member.ResolvedMember == null)
break;
completionList.Items.AddRange(
CompletionDataHelper.MemberCompletion(context, member.ResolvedMember.ReturnType, string.Empty)
);
break;
case "Property":
completionList.Items.AddRange(
typeName.GetProperties()
.Where(p => p.IsPublic && p.CanSet)
.Select(prop => new DefaultCompletionItem(prop.Name))
.Cast<ICompletionItem>()
);
break;
}
}
}
}
static string GetTypeNameFromTypeExtension(MarkupExtensionInfo info)
{
var item = info.PositionalArguments.FirstOrDefault();
@ -220,12 +240,12 @@ namespace ICSharpCode.XamlBinding @@ -220,12 +240,12 @@ namespace ICSharpCode.XamlBinding
return string.Empty;
}
static bool DoMarkupExtensionCompletion(ITextEditor editor, ParseInformation info, XamlCompletionContext context)
static bool DoMarkupExtensionCompletion(XamlCompletionContext context)
{
if (context.AttributeValue != null && !context.AttributeValue.IsString) {
var completionList = CompletionDataHelper.CreateMarkupExtensionCompletion(context, info, editor);
editor.ShowCompletionWindow(completionList);
var insightList = CompletionDataHelper.CreateMarkupExtensionInsight(context, info, editor);
if (context.Description == XamlContextDescription.InMarkupExtension && context.AttributeValue != null && !context.AttributeValue.IsString) {
var completionList = CompletionDataHelper.CreateMarkupExtensionCompletion(context);
context.Editor.ShowCompletionWindow(completionList);
var insightList = CompletionDataHelper.CreateMarkupExtensionInsight(context);
//editor.ShowInsightWindow(insightList);
return true;
}

28
src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlCompletionItemList.cs

@ -32,6 +32,22 @@ namespace ICSharpCode.XamlBinding @@ -32,6 +32,22 @@ namespace ICSharpCode.XamlBinding
return base.ProcessInput(key);
}
public static int CountWhiteSpacesAtEnd(string text)
{
if (string.IsNullOrEmpty(text))
return 0;
int i = text.Length - 1;
while (i >= 0) {
if (!char.IsWhiteSpace(text[i]))
break;
i--;
}
return text.Length - i - 1;
}
public override void Complete(CompletionContext context, ICompletionItem item)
{
base.Complete(context, item);
@ -51,15 +67,17 @@ namespace ICSharpCode.XamlBinding @@ -51,15 +67,17 @@ namespace ICSharpCode.XamlBinding
AttributeValue value = MarkupExtensionParser.ParseValue(valuePart);
if (value != null && !value.IsString) {
var markup = Utils.GetInnermostMarkup(value.ExtensionValue);
var markup = Utils.GetMarkupExtensionAtPosition(value.ExtensionValue, context.Editor.Caret.Offset);
if (markup.NamedArguments.Count > 0 || markup.PositionalArguments.Count > 0) {
int oldOffset = context.Editor.Caret.Offset;
context.Editor.Caret.Offset = context.StartOffset;
string word = context.Editor.GetWordBeforeCaret().Trim();
string word = context.Editor.GetWordBeforeCaret().TrimEnd();
int spaces = CountWhiteSpacesAtEnd(context.Editor.GetWordBeforeCaret());
int typeNameStart = markup.ExtensionType.IndexOf(':') + 1;
if (!word.EndsWith(",") && markup.ExtensionType != word) {
context.Editor.Document.Insert(context.Editor.Caret.Offset, ", ");
oldOffset += 2;
if (!word.EndsWith(",") && markup.ExtensionType.Substring(typeNameStart, markup.ExtensionType.Length - typeNameStart) != word) {
context.Editor.Document.Replace(context.Editor.Caret.Offset - spaces, spaces, ", ");
oldOffset += (2 - spaces);
}
context.Editor.Caret.Offset = oldOffset;

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

@ -47,6 +47,20 @@ namespace ICSharpCode.XamlBinding @@ -47,6 +47,20 @@ namespace ICSharpCode.XamlBinding
}
public class XamlCompletionContext : XamlContext {
public XamlCompletionContext() { }
public XamlCompletionContext(XamlContext context)
{
this.AttributeName = context.AttributeName;
this.AttributeValue = context.AttributeValue;
this.Description = context.Description;
this.ParseInformation = context.ParseInformation;
this.Path = context.Path;
this.RawAttributeValue = context.RawAttributeValue;
this.ValueStartOffset = context.ValueStartOffset;
this.XmlnsDefinitions = context.XmlnsDefinitions;
}
public char PressedKey { get; set; }
public bool Forced { get; set; }
public ITextEditor Editor { get; set; }

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

@ -5,15 +5,17 @@ @@ -5,15 +5,17 @@
// <version>$Revision: 3539 $</version>
// </file>
using ICSharpCode.XmlEditor;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Xml;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.XmlEditor;
namespace ICSharpCode.XamlBinding
{
@ -66,30 +68,75 @@ namespace ICSharpCode.XamlBinding @@ -66,30 +68,75 @@ namespace ICSharpCode.XamlBinding
if ((data as string) == expression) {
return ResolveElementName(expression + "Extension") ?? ResolveElementName(expression);
} else {
var value = data as AttributeValue;
if (value != null && value.IsString) {
return ResolveElementName(expression) ?? ResolveAttribute(expression);
}
if (data is KeyValuePair<string, AttributeValue>) {
var pair = (KeyValuePair<string, AttributeValue>)data;
var member = ResolveAttribute(pair.Key);
if (pair.Value.StartOffset + pair.Key.Length >= context.ValueStartOffset) {
return member;
} else {
if (pair.Value.IsString && member != null)
return ResolveAttributeValue(member.ResolvedMember, expression);
MarkupExtensionInfo info = Utils.GetMarkupExtensionAtPosition(context.AttributeValue.ExtensionValue, context.ValueStartOffset);
TypeResolveResult extensionType = (ResolveElementName(info.ExtensionType + "Extension") ?? ResolveElementName(info.ExtensionType)) as TypeResolveResult;
// TODO : hardcode x:Type and x:Static
if (extensionType != null && extensionType.ResolvedType != null) {
var value = data as AttributeValue;
switch (extensionType.ResolvedType.FullyQualifiedName) {
case "System.Windows.Markup.StaticExtension":
if (value != null && value.IsString) {
return ResolveElementName(expression) ?? ResolveAttribute(expression);
}
if (data is KeyValuePair<string, AttributeValue>) {
var pair = (KeyValuePair<string, AttributeValue>)data;
var member = ResolveNamedAttribute(pair.Key);
if (pair.Value.StartOffset + pair.Key.Length >= context.ValueStartOffset) {
return member;
} else {
if (pair.Value.IsString && member != null)
return ResolveAttributeValue(member.ResolvedMember, expression) ?? ResolveElementName(expression);
}
}
break;
case "System.Windows.Markup.TypeExtension":
if (value != null && value.IsString) {
return ResolveElementName(expression) ?? ResolveAttribute(expression);
}
if (data is KeyValuePair<string, AttributeValue>) {
var pair = (KeyValuePair<string, AttributeValue>)data;
var member = ResolveNamedAttribute(pair.Key);
if (pair.Value.StartOffset + pair.Key.Length >= context.ValueStartOffset) {
return member;
} else {
if (pair.Value.IsString && member != null)
return ResolveAttributeValue(member.ResolvedMember, expression) ?? ResolveElementName(expression);
}
}
break;
}
}
return null;
}
}
MemberResolveResult ResolveNamedAttribute(string expression)
{
MarkupExtensionInfo info = Utils.GetMarkupExtensionAtPosition(context.AttributeValue.ExtensionValue, context.ValueStartOffset);
TypeResolveResult extensionType = (ResolveElementName(info.ExtensionType + "Extension") ?? ResolveElementName(info.ExtensionType)) as TypeResolveResult;
if (extensionType != null && extensionType.ResolvedType != null) {
return ResolvePropertyName(extensionType.ResolvedType, expression, false);
}
return null;
}
ResolveResult ResolveElementName(string exp)
{
string xmlNamespace;
string name;
foreach (var s in context.XmlnsDefinitions) {
Debug.Print(s.Key + " " + s.Value);
}
this.resolveExpression = exp;
if (resolveExpression.Contains(":")) {
string prefix = resolveExpression.Substring(0, resolveExpression.IndexOf(':'));
@ -125,31 +172,37 @@ namespace ICSharpCode.XamlBinding @@ -125,31 +172,37 @@ namespace ICSharpCode.XamlBinding
IProjectContent pc = context.ParseInformation.BestCompilationUnit.ProjectContent;
IReturnType resolvedType = XamlCompilationUnit.FindType(pc, xmlNamespace, className);
if (resolvedType != null && resolvedType.GetUnderlyingClass() != null) {
IMember member = resolvedType.GetProperties().Find(delegate(IProperty p) { return p.Name == propertyName; });
if (member == null) {
member = resolvedType.GetEvents().Find(delegate(IEvent p) { return p.Name == propertyName; });
}
if (member == null && allowAttached) {
IMethod method = resolvedType.GetMethods().Find(
return ResolvePropertyName(resolvedType, propertyName, allowAttached);
}
return null;
}
MemberResolveResult ResolvePropertyName(IReturnType resolvedType, string propertyName, bool allowAttached)
{
IMember member = resolvedType.GetProperties().Find(delegate(IProperty p) { return p.Name == propertyName; });
if (member == null) {
member = resolvedType.GetEvents().Find(delegate(IEvent p) { return p.Name == propertyName; });
}
if (member == null && allowAttached) {
IMethod method = resolvedType.GetMethods().Find(
delegate(IMethod p) {
return p.IsStatic && p.Parameters.Count == 1 && p.Name == "Get" + propertyName;
});
member = method;
if (member != null) {
member = new DefaultProperty(resolvedType.GetUnderlyingClass(), propertyName) { ReturnType = method.ReturnType };
} else {
IMethod m = resolvedType.GetMethods().Find(
delegate(IMethod p) {
return p.IsStatic && p.Parameters.Count == 1 && p.Name == "Get" + propertyName;
return p.IsPublic && p.IsStatic && p.Parameters.Count == 2 && (p.Name == "Add" + propertyName + "Handler" || p.Name == "Remove" + propertyName + "Handler");
});
member = method;
if (member != null) {
member = new DefaultProperty(resolvedType.GetUnderlyingClass(), propertyName) { ReturnType = method.ReturnType };
} else {
IMethod m = resolvedType.GetMethods().Find(
delegate(IMethod p) {
return p.IsPublic && p.IsStatic && p.Parameters.Count == 2 && (p.Name == "Add" + propertyName + "Handler" || p.Name == "Remove" + propertyName + "Handler");
});
member = m;
if (member != null)
member = new DefaultEvent(resolvedType.GetUnderlyingClass(), propertyName) { ReturnType = m.Parameters[1].ReturnType };
}
member = m;
if (member != null)
member = new DefaultEvent(resolvedType.GetUnderlyingClass(), propertyName) { ReturnType = m.Parameters[1].ReturnType };
}
if (member != null)
return new MemberResolveResult(callingClass, null, member);
}
if (member != null)
return new MemberResolveResult(callingClass, null, member);
return null;
}

Loading…
Cancel
Save