Browse Source

- XAML binding clean up

- simplified code
- most of completion now works through CtrlSpace

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@4104 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts^2
Siegfried Pammer 16 years ago
parent
commit
14f192be46
  1. 380
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/CompletionDataHelper.cs
  2. 18
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/Extensions.cs
  3. 8
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/MarkupExtensionInfo.cs
  4. 9
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/MarkupExtensionParser.cs
  5. 4
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/MarkupExtensionTokenKind.cs
  6. 4
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/MarkupExtensionTokenizer.cs
  7. 19
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/Utils.cs
  8. 1
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlBinding.csproj
  9. 311
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlCodeCompletionBinding.cs
  10. 4
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlColorizerServer.cs
  11. 88
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlCompletionItem.cs
  12. 18
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlCompletionSettings.cs
  13. 32
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlContext.cs
  14. 4
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlExpressionFinder.cs
  15. 2
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlParser.cs

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

@ -7,6 +7,7 @@ @@ -7,6 +7,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Xml;
@ -15,6 +16,7 @@ using ICSharpCode.SharpDevelop; @@ -15,6 +16,7 @@ using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.XmlEditor;
using LoggingService = ICSharpCode.Core.LoggingService;
namespace ICSharpCode.XamlBinding
{
@ -34,7 +36,71 @@ namespace ICSharpCode.XamlBinding @@ -34,7 +36,71 @@ namespace ICSharpCode.XamlBinding
public const string XamlNamespace = "http://schemas.microsoft.com/winfx/2006/xaml";
static List<ICompletionItem> CreateListForAttributeName(ParseInformation parseInfo, string fileContent, XamlExpressionContext context, string[] existingItems)
public static XamlContext ResolveContext(ITextEditor editor, char typedValue)
{
string text = editor.Document.Text;
int offset = editor.Caret.Offset;
XamlResolver resolver = new XamlResolver();
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);
ResolveResult rr = null;
AttributeValue value = null;
XamlExpressionContext cxt = new XamlExpressionContext(path, attribute, inAttributeValue);
if (!string.IsNullOrEmpty(attribute)) {
rr = resolver.Resolve(new ExpressionResult(attribute, cxt) { Region = new DomRegion(1,1) }, info, text);
}
value = MarkupExtensionParser.ParseValue(attributeValue);
XamlContextDescription description = XamlContextDescription.InTag;
if (path == null || path.Elements.Count == 0) {
description = XamlContextDescription.AtTag;
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().Equals(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;
var context = new XamlContext() {
PressedKey = typedValue,
Description = description,
ResolvedExpression = rr,
AttributeName = attribute,
AttributeValue = value,
ValueStartOffset = offsetFromValueStart,
Path = (path == null || path.Elements.Count == 0) ? null : path
};
LoggingService.Debug(context);
return context;
}
static List<ICompletionItem> CreateListForAttributeName(ParseInformation parseInfo, XamlExpressionContext context, string[] existingItems)
{
if (context.ElementPath.Elements.Count == 0)
return null;
@ -69,7 +135,7 @@ namespace ICSharpCode.XamlBinding @@ -69,7 +135,7 @@ namespace ICSharpCode.XamlBinding
return false;
}
public static List<ICompletionItem> CreateListForElement(ParseInformation parseInfo, string fileContent, int caretLine, int caretColumn)
public static IList<ICompletionItem> CreateListForElement(ParseInformation parseInfo, string fileContent, int caretLine, int caretColumn)
{
var items = GetClassesFromContext(parseInfo, fileContent, caretLine, caretColumn);
var result = new List<ICompletionItem>();
@ -87,14 +153,7 @@ namespace ICSharpCode.XamlBinding @@ -87,14 +153,7 @@ namespace ICSharpCode.XamlBinding
return result;
}
static bool IsCollectionType(IReturnType rt)
{
if (rt == null)
return false;
return rt.GetMethods().Any(m => m.Name == "Add" && m.IsPublic);
}
public static List<ICompletionItem> CreateListOfMarkupExtensions(ParseInformation parseInfo, string fileContent, int caretLine, int caretColumn)
public static IList<ICompletionItem> CreateListOfMarkupExtensions(ParseInformation parseInfo, string fileContent, int caretLine, int caretColumn)
{
var list = CreateListForElement(parseInfo, fileContent, caretLine, caretColumn);
@ -105,7 +164,7 @@ namespace ICSharpCode.XamlBinding @@ -105,7 +164,7 @@ namespace ICSharpCode.XamlBinding
selItem => {
var it = selItem as XamlCompletionItem;
string text = it.Text;
if (it.Text.EndsWith("Extension"))
if (it.Text.EndsWith("Extension", StringComparison.Ordinal))
text = text.Remove(it.Text.Length - "Extension".Length);
return new XamlCompletionItem(text, it.Entity) as ICompletionItem;
}
@ -114,124 +173,249 @@ namespace ICSharpCode.XamlBinding @@ -114,124 +173,249 @@ namespace ICSharpCode.XamlBinding
return neededItems.ToList();
}
public static ICompletionItemList CreateListForContext(ITextEditor editor, XamlContext context, XmlElementPath path, IEntity entity)
public static ICompletionItemList CreateListForContext(ITextEditor editor, XamlContext context)
{
XamlCompletionItemList list = new XamlCompletionItemList();
ParseInformation info = ParserService.GetParseInformation(editor.FileName);
switch (context) {
case XamlContext.AtTag:
switch (context.Description) {
case XamlContextDescription.AtTag:
list.Items.AddRange(standardElements);
list.Items.AddRange(CreateListForElement(info, editor.Document.Text, editor.Caret.Line, editor.Caret.Column));
break;
case XamlContext.InTag:
list.Items.AddRange(CreateListForAttributeName(info, editor.Document.Text, new XamlExpressionContext(path, null, false), Utils.GetListOfExistingAttributeNames(editor.Document.Text, editor.Caret.Offset)));
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));
QualifiedName last = path.Elements[path.Elements.Count - 1];
QualifiedName last = context.Path.Elements[context.Path.Elements.Count - 1];
TypeResolveResult trr = new XamlResolver().Resolve(new ExpressionResult(last.Name, new XamlExpressionContext(path, null, false)), info, editor.Document.Text) as TypeResolveResult;
TypeResolveResult trr = new XamlResolver().Resolve(new ExpressionResult(last.Name, new XamlExpressionContext(context.Path, null, false)), 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));
list.Items.AddRange(GetListOfAttachedEvents(info, editor.Document.Text, editor.Caret.Line, editor.Caret.Column));
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(standardAttributes);
break;
case XamlContext.InAttributeValue:
case XamlContextDescription.InAttributeValue:
XamlCodeCompletionBinding.Instance.CtrlSpace(editor);
break;
}
list.SortItems();
if (list.Items.Count >= 1)
list.SuggestedItem = list.Items[0];
return list;
}
public static ICompletionItemList CreateMarkupExtensionCompletion(MarkupExtensionInfo markup, ParseInformation info, ITextEditor editor, char ch)
public static IEnumerable<IInsightItem> CreateMarkupExtensionInsight(XamlContext context, ParseInformation info, ITextEditor editor)
{
var markup = GetInnermostMarkup(context.AttributeValue.ExtensionValue);
var trr = ResolveMarkupExtensionType(markup, info, editor, context.Path);
if (trr != null) {
var ctors = trr.ResolvedType
.GetMethods()
.Where(m => m.IsPublic && m.IsConstructor && m.Parameters.Count >= markup.PositionalArguments.Count + 1)
.OrderBy(m => m.Parameters.Count);
yield return new MarkupExtensionInsightItem(new DefaultMethod(trr.ResolvedClass, trr.ResolvedClass.Name));
foreach (var ctor in ctors)
yield return new MarkupExtensionInsightItem(ctor);
}
}
public static ICompletionItemList CreateMarkupExtensionCompletion(XamlContext context, ParseInformation info, ITextEditor editor)
{
var list = new XamlCompletionItemList();
var path = XmlParser.GetActiveElementStartPathAtIndex(editor.Document.Text, editor.Caret.Offset);
var innerMarkup = GetInnermostMarkup(markup);
var markup = GetInnermostMarkup(context.AttributeValue.ExtensionValue);
var trr = ResolveMarkupExtensionType(innerMarkup, info, editor, path);
var trr = ResolveMarkupExtensionType(markup, info, editor, path);
if (trr == null) {
list.Items.AddRange(CreateListOfMarkupExtensions(info, editor.Document.Text, editor.Caret.Line, editor.Caret.Column));
list.PreselectionLength = innerMarkup.Type.Length;
list.SuggestedItem = list.Items.FirstOrDefault(item => item.Text.StartsWith(innerMarkup.Type));
list.PreselectionLength = markup.ExtensionType.Length;
} else {
if (markup.NamedArguments.Count == 0) {
if (trr.ResolvedType != null) {
switch (trr.ResolvedType.FullyQualifiedName) {
case "System.Windows.Markup.ArrayExtension":
case "System.Windows.Markup.NullExtension":
// x:Null/x:Array does not need completion, ignore it
break;
case "System.Windows.Markup.StaticExtension":
if (markup.PositionalArguments.Count == 1 && ch == ' ')
break;
if (markup.PositionalArguments.Count <= 1) {
if (ch == '.') {
// TODO : enum and field completion
} else {
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));
}
AttributeValue selItem = markup.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));
}
}
}
break;
case "System.Windows.Markup.TypeExtension":
if (markup.PositionalArguments.Count == 1 && ch == ' ')
break;
if (markup.PositionalArguments.Count <= 1) {
list.Items.AddRange(CreateListForElement(info, editor.Document.Text, editor.Caret.Line, editor.Caret.Column));
AttributeValue selItem = markup.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));
}
}
break;
default:
var ctors = trr.ResolvedType
.GetMethods()
.Where(m => m.IsPublic && m.IsConstructor && m.Parameters.Count >= markup.PositionalArguments.Count + 1)
.OrderBy(m => m.Parameters.Count);
//var ctor = FindCompletableCtor(ctors, markup.PositionalArguments.Count)
break;
}
}
} else {
// TODO : named args completion
if (trr.ResolvedType != null) {
if (markup.NamedArguments.Count == 0) {
DoPositionalArgsCompletion(list, context, trr, info, editor);
DoNamedArgsCompletion(list, trr, markup);
} else
DoNamedArgsCompletion(list, trr, markup);
}
}
list.SortItems();
if (list.SuggestedItem == null)
list.SuggestedItem = list.Items.FirstOrDefault();
return list;
}
static void DoNamedArgsCompletion(XamlCompletionItemList list, TypeResolveResult trr, MarkupExtensionInfo markup)
{
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));
}
}
static void DoPositionalArgsCompletion(XamlCompletionItemList list, XamlContext context, TypeResolveResult trr, ParseInformation info, ITextEditor editor)
{
switch (trr.ResolvedType.FullyQualifiedName) {
case "System.Windows.Markup.ArrayExtension":
case "System.Windows.Markup.NullExtension":
// 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, info, editor);
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));
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));
}
}
break;
default:
// var ctors = trr.ResolvedType
// .GetMethods()
// .Where(m => m.IsPublic && m.IsConstructor && m.Parameters.Count >= markup.PositionalArguments.Count + 1)
// .OrderBy(m => m.Parameters.Count);
//
// //var ctor = FindCompletableCtor(ctors, markup.PositionalArguments.Count)
break;
}
}
public static IEnumerable<IInsightItem> MemberInsight(MemberResolveResult mrr)
{
switch (mrr.ResolvedType.FullyQualifiedName) {
case "System.Windows.Thickness":
yield return new MemberInsightItem(mrr.ResolvedMember, "left");
yield return new MemberInsightItem(mrr.ResolvedMember, "left, top");
yield return new MemberInsightItem(mrr.ResolvedMember, "left, top, right, bottom");
break;
case "System.Windows.Size":
yield return new MemberInsightItem(mrr.ResolvedMember, "width, height");
break;
case "System.Windows.Point":
yield return new MemberInsightItem(mrr.ResolvedMember, "x, y");
break;
case "System.Windows.Rect":
yield return new MemberInsightItem(mrr.ResolvedMember, "x, y, width, height");
break;
}
}
public static IEnumerable<ICompletionItem> MemberCompletion(ITextEditor editor, IReturnType type)
{
if (type == null || type.GetUnderlyingClass() == null)
yield break;
var c = type.GetUnderlyingClass();
switch (c.ClassType) {
case ClassType.Enum:
foreach (IField f in c.Fields)
yield return new XamlCompletionItem(f);
break;
case ClassType.Struct:
if (c.FullyQualifiedName == "System.Boolean") {
yield return new DefaultCompletionItem("True");
yield return new DefaultCompletionItem("False");
}
break;
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)
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))
yield return eventItem;
}
}
break;
}
}
static IEntity ResolveAttribute(string attribute, ITextEditor editor)
{
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;
return mrr.ResolvedMember;
}
static void DoStaticExtensionCompletion(XamlCompletionItemList list, XamlContext context, ParseInformation info, ITextEditor editor)
{
AttributeValue selItem = context.AttributeValue.ExtensionValue.PositionalArguments.LastOrDefault();
if (context.PressedKey == '.') {
if (selItem != null && selItem.IsString) {
var rr = ResolveStringValue(selItem.StringValue, list, context.Path, info, editor) as TypeResolveResult;
if (rr != null)
list.Items.AddRange(MemberCompletion(editor, 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, list, context.Path, info, editor) as TypeResolveResult;
if (rr != null) {
list.Items.AddRange(MemberCompletion(editor, 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);
} else {
DoStaticTypeCompletion(selItem, list, info, editor);
}
}
}
static void DoStaticTypeCompletion(AttributeValue selItem, XamlCompletionItemList list, ParseInformation info, ITextEditor editor)
{
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));
}
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));
}
}
static ResolveResult ResolveStringValue(string value, XamlCompletionItemList list, XmlElementPath path, ParseInformation info, ITextEditor editor)
{
var resolver = new XamlResolver();
var rr = resolver.Resolve(new ExpressionResult(value, new XamlExpressionContext(path, string.Empty, false)), info, editor.Document.Text);
return rr;
}
static IMethod FindCompletableCtor(IList<IMethod> ctors, int index)
{
@ -258,20 +442,20 @@ namespace ICSharpCode.XamlBinding @@ -258,20 +442,20 @@ namespace ICSharpCode.XamlBinding
static TypeResolveResult ResolveMarkupExtensionType(MarkupExtensionInfo markup, ParseInformation info, ITextEditor editor, XmlElementPath path)
{
XamlResolver resolver = new XamlResolver();
TypeResolveResult trr = resolver.Resolve(new ExpressionResult(markup.Type, new XamlExpressionContext(path, null, false)), info, editor.Document.Text) as TypeResolveResult;
if (trr == null) trr = resolver.Resolve(new ExpressionResult(markup.Type + "Extension", new XamlExpressionContext(path, null, false)), info, editor.Document.Text) as TypeResolveResult;
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;
return trr;
}
public static void AddMatchingEventHandlers(ITextEditor editor, IMethod delegateInvoker, List<ICompletionItem> list)
public static IEnumerable<ICompletionItem> AddMatchingEventHandlers(ITextEditor editor, IMethod delegateInvoker)
{
ParseInformation p = ParserService.GetParseInformation(editor.FileName);
var unit = p.MostRecentCompilationUnit;
var loc = editor.Document.OffsetToPosition(editor.Caret.Offset);
IClass c = unit.GetInnermostClass(loc.Line, loc.Column);
if (c == null)
return;
yield break;
CompoundClass compound = c.GetCompoundClass() as CompoundClass;
if (compound != null) {
foreach (IClass part in compound.Parts) {
@ -289,7 +473,7 @@ namespace ICSharpCode.XamlBinding @@ -289,7 +473,7 @@ namespace ICSharpCode.XamlBinding
break;
}
if (equal) {
list.Add(new XamlCompletionItem(m));
yield return new XamlCompletionItem(m);
}
}
}
@ -328,7 +512,7 @@ namespace ICSharpCode.XamlBinding @@ -328,7 +512,7 @@ namespace ICSharpCode.XamlBinding
}
}
static List<ICompletionItem> GetListOfAttachedProperties(ParseInformation parseInfo, string fileContent, int caretLine, int caretColumn)
static List<ICompletionItem> GetListOfAttachedProperties(ParseInformation parseInfo, string fileContent, int caretLine, int caretColumn, string[] existingItems)
{
using (XmlTextReader r = new XmlTextReader(new StringReader(fileContent))) {
try {
@ -378,7 +562,10 @@ namespace ICSharpCode.XamlBinding @@ -378,7 +562,10 @@ namespace ICSharpCode.XamlBinding
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;
}));
}
)
.Where(item => !existingItems.Any(str => str == item.Text))
);
}
}
}
@ -387,7 +574,7 @@ namespace ICSharpCode.XamlBinding @@ -387,7 +574,7 @@ namespace ICSharpCode.XamlBinding
}
}
static List<ICompletionItem> GetListOfAttachedEvents(ParseInformation parseInfo, string fileContent, int caretLine, int caretColumn)
static List<ICompletionItem> GetListOfAttachedEvents(ParseInformation parseInfo, string fileContent, int caretLine, int caretColumn, string[] existingItems)
{
var items = GetClassesFromContext(parseInfo, fileContent, caretLine, caretColumn);
var result = new List<ICompletionItem>();
@ -431,6 +618,7 @@ namespace ICSharpCode.XamlBinding @@ -431,6 +618,7 @@ namespace ICSharpCode.XamlBinding
}
) as ICompletionItem
)
.Where(item => !existingItems.Any(str => str == item.Text))
);
}
}

18
src/AddIns/BackendBindings/XamlBinding/XamlBinding/Extensions.cs

@ -19,5 +19,23 @@ namespace ICSharpCode.XamlBinding @@ -19,5 +19,23 @@ namespace ICSharpCode.XamlBinding
{
return s.Split(delimiters, options);
}
public static bool EndsWith(this string s, StringComparison comparison, params char[] characters)
{
foreach (var c in characters) {
if (s.EndsWith(c.ToString(), comparison))
return true;
}
return false;
}
public static QualifiedName LastOrDefault(this QualifiedNameCollection coll)
{
if (coll.Count > 0)
return coll[coll.Count - 1];
return null;
}
}
}

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

@ -17,9 +17,9 @@ namespace ICSharpCode.XamlBinding @@ -17,9 +17,9 @@ namespace ICSharpCode.XamlBinding
{
public class MarkupExtensionInfo
{
public string Type { get; set; }
public IList<AttributeValue> PositionalArguments { get; set; }
public IDictionary<string, AttributeValue> NamedArguments { get; set; }
public string ExtensionType { get; set; }
public IList<AttributeValue> PositionalArguments { get; private set; }
public IDictionary<string, AttributeValue> NamedArguments { get; private set; }
public MarkupExtensionInfo()
: this(string.Empty, new List<AttributeValue>(), new Dictionary<string, AttributeValue>())
@ -28,7 +28,7 @@ namespace ICSharpCode.XamlBinding @@ -28,7 +28,7 @@ namespace ICSharpCode.XamlBinding
public MarkupExtensionInfo(string type, IList<AttributeValue> posArgs, IDictionary<string, AttributeValue> namedArgs)
{
this.Type = type;
this.ExtensionType = type;
this.PositionalArguments = posArgs;
this.NamedArguments = namedArgs;
}

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

@ -21,12 +21,12 @@ namespace ICSharpCode.XamlBinding @@ -21,12 +21,12 @@ namespace ICSharpCode.XamlBinding
string argumentName = null;
var token = tokenizer.NextToken();
while (token.Kind != MarkupExtensionTokenKind.EOF) {
while (token.Kind != MarkupExtensionTokenKind.EndOfFile) {
switch (token.Kind) {
case MarkupExtensionTokenKind.TypeName:
info.Type = token.Value;
info.ExtensionType = token.Value;
break;
case MarkupExtensionTokenKind.Membername:
case MarkupExtensionTokenKind.MemberName:
argumentName = token.Value;
break;
case MarkupExtensionTokenKind.String:
@ -49,6 +49,9 @@ namespace ICSharpCode.XamlBinding @@ -49,6 +49,9 @@ namespace ICSharpCode.XamlBinding
public static AttributeValue ParseValue(string text)
{
if (string.IsNullOrEmpty(text))
return new AttributeValue(string.Empty);
if (text.StartsWith("{", StringComparison.OrdinalIgnoreCase))
return new AttributeValue(Parse(text));
else

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

@ -11,13 +11,13 @@ namespace ICSharpCode.XamlBinding @@ -11,13 +11,13 @@ namespace ICSharpCode.XamlBinding
{
public enum MarkupExtensionTokenKind
{
EOF,
EndOfFile,
OpenBrace,
CloseBrace,
Equals,
Comma,
TypeName,
Membername,
MemberName,
String
}
}

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

@ -46,7 +46,7 @@ namespace ICSharpCode.XamlBinding @@ -46,7 +46,7 @@ namespace ICSharpCode.XamlBinding
if (tokens.Count > 0)
return tokens.Dequeue();
else
return new MarkupExtensionToken(MarkupExtensionTokenKind.EOF, "");
return new MarkupExtensionToken(MarkupExtensionTokenKind.EndOfFile, "");
}
void AddToken(MarkupExtensionTokenKind kind, string val)
@ -137,7 +137,7 @@ namespace ICSharpCode.XamlBinding @@ -137,7 +137,7 @@ namespace ICSharpCode.XamlBinding
}
string valueText = b.ToString();
if (pos < text.Length && text[pos] == '=') {
AddToken(MarkupExtensionTokenKind.Membername, valueText.Trim());
AddToken(MarkupExtensionTokenKind.MemberName, valueText.Trim());
} else {
AddToken(MarkupExtensionTokenKind.String, valueText);
}

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

@ -212,6 +212,7 @@ namespace ICSharpCode.XamlBinding @@ -212,6 +212,7 @@ namespace ICSharpCode.XamlBinding
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 + " />";
@ -228,5 +229,23 @@ namespace ICSharpCode.XamlBinding @@ -228,5 +229,23 @@ namespace ICSharpCode.XamlBinding
return item.Key.Substring("xmlns:".Length);
return string.Empty;
}
public static bool IsInsideXmlComment(string xaml, int offset)
{
if (xaml == null)
throw new ArgumentNullException("xaml");
if (offset < 0)
throw new ArgumentOutOfRangeException("offset", offset, "Value must be between 0 and " + (xaml.Length - 1));
if (offset >= xaml.Length)
offset = xaml.Length - 1;
string interestingPart = xaml.Substring(0, offset);
int end = interestingPart.LastIndexOf("-->");
interestingPart = (end > -1) ? interestingPart.Substring(end, interestingPart.Length - end) : interestingPart;
return interestingPart.LastIndexOf("<!--") != -1;
}
}
}

1
src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlBinding.csproj

@ -76,6 +76,7 @@ @@ -76,6 +76,7 @@
<Compile Include="XamlCompilationUnit.cs" />
<Compile Include="XamlCompletionItem.cs" />
<Compile Include="XamlCompletionItemList.cs" />
<Compile Include="XamlCompletionSettings.cs" />
<Compile Include="XamlContext.cs" />
<Compile Include="XamlExpressionContext.cs" />
<Compile Include="XamlExpressionFinder.cs">

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

@ -35,201 +35,136 @@ namespace ICSharpCode.XamlBinding @@ -35,201 +35,136 @@ namespace ICSharpCode.XamlBinding
XamlParser parser = new XamlParser();
ParseInformation info = ParserService.GetParseInformation(editor.FileName);
XmlElementPath path;
int offset;
XamlContext context = CompletionDataHelper.ResolveContext(editor, ch);
ICompletionItemList list;
if (context.Description == XamlContextDescription.InComment)
return CodeCompletionKeyPressResult.None;
switch (ch) {
case '<':
int prevLTCharPos = Utils.GetPreviousLTCharPos(editor.Document.Text, editor.Caret.Offset) + 1;
path = XmlParser.GetActiveElementStartPathAtIndex(editor.Document.Text, prevLTCharPos);
if (path != null && path.Elements.Count > 0) {
ICompletionItemList list = CompletionDataHelper.CreateListForContext(editor, XamlContext.AtTag, path, null);
editor.ShowCompletionWindow(list);
return CodeCompletionKeyPressResult.Completed;
}
break;
list = CompletionDataHelper.CreateListForContext(editor, context);
editor.ShowCompletionWindow(list);
return CodeCompletionKeyPressResult.Completed;
case '>': // XML tag completion
offset = editor.Caret.Offset;
if (offset > 0) {
int searchOffset = offset - 1;
char c = editor.Document.GetCharAt(searchOffset);
while (char.IsWhiteSpace(c)) {
searchOffset--;
c = editor.Document.GetCharAt(searchOffset);
}
if (c != '/') {
string document = editor.Document.Text.Insert(offset, ">");
path = XmlParser.GetActiveElementStartPathAtIndex(document, offset);
if (path != null && path.Elements.Count > 0) {
QualifiedName last = path.Elements[path.Elements.Count - 1];
if (!Utils.HasMatchingEndTag(last.Name, document, offset) && !last.Name.StartsWith("/")) {
editor.Document.Insert(offset, "></" + last.Name + ">");
editor.Caret.Offset = offset + 1;
return CodeCompletionKeyPressResult.EatKey;
}
}
}
}
if (DoXmlTagCompletion(editor))
return CodeCompletionKeyPressResult.EatKey;
break;
case '"':
offset = editor.Caret.Offset;
if (!XmlParser.IsInsideAttributeValue(editor.Document.Text, offset)) {
int search = offset + 1;
if (!XmlParser.IsInsideAttributeValue(editor.Document.Text, editor.Caret.Offset)) {
int search = editor.Caret.Offset + 1;
while (search < editor.Document.TextLength - 1 && char.IsWhiteSpace(editor.Document.GetCharAt(search)))
search++;
if (editor.Document.GetCharAt(search) != '"') {
editor.Document.Insert(offset, "\"");
editor.Caret.Offset = offset;
return CodeCompletionKeyPressResult.CompletedIncludeKeyInCompletion;
editor.Document.Insert(editor.Caret.Offset, "\"\"");
editor.Caret.Offset--;
this.CtrlSpace(editor);
return CodeCompletionKeyPressResult.EatKey;
}
}
break;
case '{': // starting point for Markup Extension Completion
offset = editor.Caret.Offset;
editor.Document.Insert(offset, "{}");
editor.Caret.Offset = offset + 1;
path = XmlParser.GetActiveElementStartPath(editor.Document.Text, editor.Caret.Offset);
if (path != null && path.Elements.Count > 0) {
int offsetFromValueStart = Utils.GetOffsetFromValueStart(editor.Document.Text, editor.Caret.Offset);
string allValue = XmlParser.GetAttributeValueAtIndex(editor.Document.Text, editor.Caret.Offset);
string attribute = XmlParser.GetAttributeNameAtIndex(editor.Document.Text, editor.Caret.Offset);
string interestingPart = allValue.Substring(0, offsetFromValueStart);
if (!string.IsNullOrEmpty(context.AttributeName) && XmlParser.IsInsideAttributeValue(editor.Document.Text, editor.Caret.Offset)) {
editor.Document.Insert(editor.Caret.Offset, "{}");
editor.Caret.Offset--;
AttributeValue value = MarkupExtensionParser.ParseValue(interestingPart);
if (DoMarkupExtensionCompletion(editor, info, path, attribute, interestingPart, offsetFromValueStart, value, true, ch))
return CodeCompletionKeyPressResult.EatKey;
}
break;
case ' ':
path = XmlParser.GetActiveElementStartPathAtIndex(editor.Document.Text, editor.Caret.Offset);
if (path != null && path.Elements.Count > 0) {
if (!XmlParser.IsInsideAttributeValue(editor.Document.Text, editor.Caret.Offset)) {
ICompletionItemList list = CompletionDataHelper.CreateListForContext(editor, XamlContext.InTag, path, null);
editor.ShowCompletionWindow(list);
return CodeCompletionKeyPressResult.Completed;
} else {
int offsetFromValueStart = Utils.GetOffsetFromValueStart(editor.Document.Text, editor.Caret.Offset);
string allValue = XmlParser.GetAttributeValueAtIndex(editor.Document.Text, editor.Caret.Offset);
string attribute = XmlParser.GetAttributeNameAtIndex(editor.Document.Text, editor.Caret.Offset);
string interestingPart = allValue.Substring(0, offsetFromValueStart);
AttributeValue value = MarkupExtensionParser.ParseValue(interestingPart);
if (DoMarkupExtensionCompletion(editor, info, path, attribute, allValue, offsetFromValueStart, value, false, ch))
return CodeCompletionKeyPressResult.Completed;
}
DoMarkupExtensionCompletion(editor, info, CompletionDataHelper.ResolveContext(editor, '{'));
return CodeCompletionKeyPressResult.EatKey;
}
break;
case '.':
path = XmlParser.GetActiveElementStartPathAtIndex(editor.Document.Text, editor.Caret.Offset);
if (path != null && path.Elements.Count > 0) {
if (!XmlParser.IsInsideAttributeValue(editor.Document.Text, editor.Caret.Offset)) {
ICompletionItemList list = CompletionDataHelper.CreateListForContext(editor, XamlContext.InTag, path, null);
editor.ShowCompletionWindow(list);
return CodeCompletionKeyPressResult.Completed;
}
if (context.Path != null && !XmlParser.IsInsideAttributeValue(editor.Document.Text, editor.Caret.Offset)) {
list = CompletionDataHelper.CreateListForContext(editor, context);
editor.ShowCompletionWindow(list);
return CodeCompletionKeyPressResult.Completed;
}
break;
case ':':
path = XmlParser.GetActiveElementStartPathAtIndex(editor.Document.Text, editor.Caret.Offset);
if (path != null && path.Elements.Count > 0) {
if (XmlParser.GetQualifiedAttributeNameAtIndex(editor.Document.Text, editor.Caret.Offset) == null) {
ICompletionItemList list = CompletionDataHelper.CreateListForContext(editor, XamlContext.AtTag, path, null);
editor.ShowCompletionWindow(list);
return CodeCompletionKeyPressResult.CompletedIncludeKeyInCompletion;
}
if (context.Path != null && XmlParser.GetQualifiedAttributeNameAtIndex(editor.Document.Text, editor.Caret.Offset) == null) {
list = CompletionDataHelper.CreateListForContext(editor, context);
editor.ShowCompletionWindow(list);
return CodeCompletionKeyPressResult.CompletedIncludeKeyInCompletion;
}
break;
case '/': // ignore '/' when trying to type '/>'
return CodeCompletionKeyPressResult.None;
case '=':
offset = editor.Caret.Offset;
path = XmlParser.GetActiveElementStartPathAtIndex(editor.Document.Text, offset);
if (!XmlParser.IsInsideAttributeValue(editor.Document.Text, editor.Caret.Offset)) {
int searchOffset = offset + 1;
int searchOffset = editor.Caret.Offset + 1;
while (char.IsWhiteSpace(editor.Document.GetCharAt(searchOffset)))
searchOffset++;
if (editor.Document.GetCharAt(searchOffset) != '"') {
// if (path != null && path.Elements.Count > 0) {
// string attr = editor.GetWordBeforeCaret();
// ResolveResult rr = resolver.Resolve(new ExpressionResult(attr, new XamlExpressionContext(path, attr, false)), info, editor.Document.Text);
//
// if (rr == null) {
// editor.Document.Insert(offset, "=\"\"");
// editor.Caret.Offset = offset + 2;
//
// return CodeCompletionKeyPressResult.EatKey;
// }
//
// ICompletionItemList list = CompletionDataHelper.CreateListForContext(editor, XamlContext.InAttributeValue, path, rr.ResolvedType));
// editor.ShowCompletionWindow(list);
// }
editor.Document.Insert(offset, "=\"\"");
editor.Caret.Offset = offset + 2;
return CodeCompletionKeyPressResult.EatKey;
editor.Document.Insert(editor.Caret.Offset, "=\"\"");
editor.Caret.Offset--;
} else {
editor.Document.Insert(editor.Caret.Offset, "=");
editor.Caret.Offset++;
}
this.CtrlSpace(editor);
return CodeCompletionKeyPressResult.EatKey;
}
break;
default:
if (char.IsLetter(ch)) {
offset = editor.Caret.Offset;
if (offset > 0) {
char c = editor.Document.GetCharAt(offset - 1);
path = XmlParser.GetActiveElementStartPathAtIndex(editor.Document.Text, offset);
string attribute = XmlParser.GetAttributeNameAtIndex(editor.Document.Text, editor.Caret.Offset);
string attribValue = XmlParser.GetAttributeValueAtIndex(editor.Document.Text, editor.Caret.Offset);
int offsetFromValueStart = Utils.GetOffsetFromValueStart(editor.Document.Text, editor.Caret.Offset);
if (!string.IsNullOrEmpty(attribute)) {
string interestingPart = attribValue.Substring(0, offsetFromValueStart);
AttributeValue value = MarkupExtensionParser.ParseValue(interestingPart);
if (DoMarkupExtensionCompletion(editor, info, path, attribute, attribValue, offsetFromValueStart, value, true, ch))
return CodeCompletionKeyPressResult.CompletedIncludeKeyInCompletion;
} else {
if (c == ' ' || c == '\t') {
if (path != null && path.Elements.Count > 0) {
ICompletionItemList list = CompletionDataHelper.CreateListForContext(editor, XamlContext.InTag, path, null);
editor.ShowCompletionWindow(list);
return CodeCompletionKeyPressResult.CompletedIncludeKeyInCompletion;
}
}
}
}
char c = char.IsWhiteSpace(ch) ? ch : editor.Document.GetCharAt(editor.Caret.Offset - 1);
if (!string.IsNullOrEmpty(context.AttributeName)) {
if (DoMarkupExtensionCompletion(editor, info, context))
return CodeCompletionKeyPressResult.CompletedIncludeKeyInCompletion;
} else if (context.Path != null && (c == ' ' || c == '\t')) {
list = CompletionDataHelper.CreateListForContext(editor, context);
editor.ShowCompletionWindow(list);
if (ch == ' ' || ch == '\t')
return CodeCompletionKeyPressResult.Completed;
else
return CodeCompletionKeyPressResult.CompletedIncludeKeyInCompletion;
}
break;
}
return CodeCompletionKeyPressResult.None;
}
bool DoXmlTagCompletion(ITextEditor editor)
{
int offset = editor.Caret.Offset;
if (offset > 0) {
int searchOffset = offset - 1;
char c = editor.Document.GetCharAt(searchOffset);
while (char.IsWhiteSpace(c)) {
searchOffset--;
c = editor.Document.GetCharAt(searchOffset);
}
if (c != '/') {
string document = editor.Document.Text.Insert(offset, ">");
XmlElementPath path = XmlParser.GetActiveElementStartPathAtIndex(document, offset);
if (path != null && path.Elements.Count > 0) {
QualifiedName last = path.Elements[path.Elements.Count - 1];
if (!Utils.HasMatchingEndTag(last.Name, document, offset) && !last.Name.StartsWith("/") && !last.Name.StartsWith("!--")) {
editor.Document.Insert(offset, "></" + last.Name + ">");
editor.Caret.Offset = offset + 1;
return true;
}
}
}
}
return false;
}
public bool CtrlSpace(ITextEditor editor)
{
XamlContext context = CompletionDataHelper.ResolveContext(editor, ' ');
var info = ParserService.GetParseInformation(editor.FileName);
var path = XmlParser.GetActiveElementStartPathAtIndex(editor.Document.Text, editor.Caret.Offset);
if (path != null && path.Elements.Count > 0) {
if (context.Path != null) {
if (!XmlParser.IsInsideAttributeValue(editor.Document.Text, editor.Caret.Offset)) {
var list = CompletionDataHelper.CreateListForContext(editor, XamlContext.InTag, path, null) as XamlCompletionItemList;
string starter = editor.GetWordBeforeCaret().Trim(' ', '\t', '\n', '\r');
if (!string.IsNullOrEmpty(starter)) {
var item = list.Items.FirstOrDefault(i => i.Text.StartsWith(starter, StringComparison.OrdinalIgnoreCase));
if (item != null) {
list.SuggestedItem = item;
list.PreselectionLength = starter.Length;
}
}
var list = CompletionDataHelper.CreateListForContext(editor, context) as XamlCompletionItemList;
string starter = editor.GetWordBeforeCaret();
if (!string.IsNullOrEmpty(starter) && !starter.EndsWith(StringComparison.Ordinal, ' ', '\t', '\n', '\r'))
list.PreselectionLength = starter.Length;
editor.ShowCompletionWindow(list);
return true;
} else {
@ -243,17 +178,16 @@ namespace ICSharpCode.XamlBinding @@ -243,17 +178,16 @@ namespace ICSharpCode.XamlBinding
AttributeValue value = MarkupExtensionParser.ParseValue(interestingPart);
if (!DoMarkupExtensionCompletion(editor, info, path, attribute, attribValue, offsetFromValueStart, value, true, default(char))) {
if (!DoMarkupExtensionCompletion(editor, info, context)) {
XamlResolver resolver = new XamlResolver();
var mrr = resolver.Resolve(new ExpressionResult(attribute, new XamlExpressionContext(path, attribute, false)),
var mrr = resolver.Resolve(new ExpressionResult(attribute, new XamlExpressionContext(context.Path, attribute, false)),
info, editor.Document.Text) as MemberResolveResult;
if (mrr != null && mrr.ResolvedType != null) {
var c = mrr.ResolvedType.GetUnderlyingClass();
var list = new XamlCompletionItemList();
list.Items.AddRange(MemberCompletion(editor, mrr));
if (list.Items.Count > 0) {
editor.ShowCompletionWindow(list);
}
var completionList = new XamlCompletionItemList();
completionList.Items.AddRange(CompletionDataHelper.MemberCompletion(editor, mrr.ResolvedType));
editor.ShowCompletionWindow(completionList);
editor.ShowInsightWindow(CompletionDataHelper.MemberInsight(mrr));
}
}
}
@ -261,67 +195,14 @@ namespace ICSharpCode.XamlBinding @@ -261,67 +195,14 @@ namespace ICSharpCode.XamlBinding
}
return false;
}
IEnumerable<ICompletionItem> MemberCompletion(ITextEditor editor, MemberResolveResult mrr)
{
if (mrr.ResolvedType == null && mrr.ResolvedType.GetUnderlyingClass() == null)
return Enumerable.Empty<ICompletionItem>();
var list = new List<ICompletionItem>();
var c = mrr.ResolvedType.GetUnderlyingClass();
switch (c.ClassType) {
case ClassType.Enum:
foreach (IField f in c.Fields)
list.Add(new XamlCompletionItem(f));
break;
case ClassType.Struct:
if (c.FullyQualifiedName == "System.Boolean") {
list.Add(new DefaultCompletionItem("True"));
list.Add(new DefaultCompletionItem("False"));
}
break;
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)
break;
string name = Utils.GetAttributeValue(editor.Document.Text, editor.Caret.Offset, "name");
list.Add(new NewEventCompletionItem(e, (string.IsNullOrEmpty(name)) ? item.Name : name));
CompletionDataHelper.AddMatchingEventHandlers(editor, invoker, list);
}
}
break;
}
return list;
}
static IEntity ResolveAttribute(string attribute, ITextEditor editor)
{
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;
return mrr.ResolvedMember;
}
bool DoMarkupExtensionCompletion(ITextEditor editor, ParseInformation info, XmlElementPath path,
string attribute, string attribValue, int offsetFromValueStart,
AttributeValue value, bool isCtrlSpace, char ch)
bool DoMarkupExtensionCompletion(ITextEditor editor, ParseInformation info, XamlContext context)
{
if (!value.IsString) {
var list = CompletionDataHelper.CreateMarkupExtensionCompletion(value.ExtensionValue, info, editor, ch);
editor.ShowCompletionWindow(list);
if (context.AttributeValue != null && !context.AttributeValue.IsString) {
var completionList = CompletionDataHelper.CreateMarkupExtensionCompletion(context, info, editor);
editor.ShowCompletionWindow(completionList);
var insightList = CompletionDataHelper.CreateMarkupExtensionInsight(context, info, editor);
editor.ShowInsightWindow(insightList);
return true;
}

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

@ -32,8 +32,8 @@ namespace ICSharpCode.XamlBinding @@ -32,8 +32,8 @@ namespace ICSharpCode.XamlBinding
ITextEditorProvider textEditor = e.Content as ITextEditorProvider;
if (textEditor != null) {
TextView textView = textEditor.TextEditor.GetService(typeof(TextView)) as TextView;
if (textView != null)
textView.LineTransformers.Add(new XamlColorizer(e.Content));
// if (textView != null)
// textView.LineTransformers.Add(new XamlColorizer(e.Content));
}
}
}

88
src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlCompletionItem.cs

@ -5,6 +5,7 @@ @@ -5,6 +5,7 @@
// <version>$Revision: 3731 $</version>
// </file>
using ICSharpCode.SharpDevelop;
using System;
using System.Linq;
using ICSharpCode.SharpDevelop.Dom;
@ -73,4 +74,91 @@ namespace ICSharpCode.XamlBinding @@ -73,4 +74,91 @@ namespace ICSharpCode.XamlBinding
context.EndOffset = context.StartOffset + this.HandlerName.Length;
}
}
class MarkupExtensionInsightItem : IInsightItem
{
IMethod ctor;
public MarkupExtensionInsightItem(IMethod entity)
{
if (entity == null)
throw new ArgumentNullException("entity");
this.ctor = entity;
}
public IMethod Ctor {
get { return ctor; }
}
string headerText;
bool descriptionCreated;
string description;
public object Header {
get {
if (headerText == null) {
IAmbience ambience = AmbienceService.GetCurrentAmbience();
ambience.ConversionFlags = ConversionFlags.StandardConversionFlags;
headerText = ambience.Convert(ctor);
headerText = headerText.Insert(headerText.LastIndexOf(')'), (ctor.Parameters.Count > 0 ? ", " : "") + "Named Parameters ...");
}
return headerText;
}
}
public object Content {
get {
if (!descriptionCreated) {
string entityDoc = ctor.Documentation;
if (!string.IsNullOrEmpty(entityDoc)) {
description = ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor.CodeCompletionData.ConvertDocumentation(entityDoc);
}
descriptionCreated = true;
}
return description;
}
}
}
class MemberInsightItem : IInsightItem
{
string insightText;
string headerText;
string description;
bool descriptionCreated;
IMember member;
public IMember Member {
get { return member; }
}
public MemberInsightItem(IMember member, string insightText)
{
this.member = member;
this.insightText = insightText;
}
public object Header {
get {
if (headerText == null) {
headerText = this.member.Name + "=\"" + insightText + "\"";
}
return headerText;
}
}
public object Content {
get {
if (!descriptionCreated) {
string entityDoc = member.Documentation;
if (!string.IsNullOrEmpty(entityDoc)) {
description = ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor.CodeCompletionData.ConvertDocumentation(entityDoc);
}
descriptionCreated = true;
}
return description;
}
}
}
}

18
src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlCompletionSettings.cs

@ -0,0 +1,18 @@ @@ -0,0 +1,18 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Siegfried Pammer" email="sie_pam@gmx.at"/>
// <version>$Revision$</version>
// </file>
using System;
namespace ICSharpCode.XamlBinding
{
public class XamlCompletionSettings
{
public XamlCompletionSettings()
{
}
}
}

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

@ -18,7 +18,31 @@ using ICSharpCode.XmlEditor; @@ -18,7 +18,31 @@ using ICSharpCode.XmlEditor;
namespace ICSharpCode.XamlBinding
{
public enum XamlContext {
public class XamlContext {
public XmlElementPath Path { get; set; }
public string AttributeName { get; set; }
public ResolveResult ResolvedExpression { get; set; }
public AttributeValue AttributeValue { get; set; }
public char PressedKey { get; set; }
public IEntity Entity { get; set; }
public int ValueStartOffset { get; set; }
public XamlContextDescription Description { get; set; }
public XamlContext() {}
public override string ToString()
{
return "[XamlContext" +
" Description: " + Description +
" Path: " + Path +
" AttributeName: " + AttributeName +
" ValueStartOffset: " + ValueStartOffset +
" ]";
}
}
public enum XamlContextDescription {
/// <summary>
/// After '&lt;'
/// </summary>
@ -34,6 +58,10 @@ namespace ICSharpCode.XamlBinding @@ -34,6 +58,10 @@ namespace ICSharpCode.XamlBinding
/// <summary>
/// Inside '="{}"'
/// </summary>
InMarkupExtension
InMarkupExtension,
/// <summary>
/// Inside '&lt;!-- --&gt;'
/// </summary>
InComment
}
}

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

@ -21,7 +21,7 @@ namespace ICSharpCode.XamlBinding @@ -21,7 +21,7 @@ namespace ICSharpCode.XamlBinding
{
public static readonly XamlExpressionFinder Instance = new XamlExpressionFinder();
bool IsValidChar(char c)
static bool IsValidChar(char c)
{
return char.IsLetterOrDigit(c) || c == '_' || c == ':' || c == '.';
}
@ -54,7 +54,7 @@ namespace ICSharpCode.XamlBinding @@ -54,7 +54,7 @@ namespace ICSharpCode.XamlBinding
return "";
}
ExpressionContext GetContext(string text, int offset)
static ExpressionContext GetContext(string text, int offset)
{
XmlElementPath path = XmlParser.GetActiveElementStartPathAtIndex(text, offset);
if (path == null || path.Elements.Count == 0) {

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

@ -91,7 +91,7 @@ namespace ICSharpCode.XamlBinding @@ -91,7 +91,7 @@ namespace ICSharpCode.XamlBinding
return cu;
}
IReturnType TypeFromXmlNode(XamlCompilationUnit cu, XmlReader r)
static IReturnType TypeFromXmlNode(XamlCompilationUnit cu, XmlReader r)
{
return cu.CreateType(r.NamespaceURI, r.LocalName);
}

Loading…
Cancel
Save