IEnumerable <ICompletionItem> CreateEventCompletion(XamlCompletionContext context, ITypeDefinition td) { IMethod invoker = td.GetMethods(method => method.Name == "Invoke").FirstOrDefault(); if (invoker != null && context.ActiveElement != null) { var item = context.ActiveElement; var resolver = new XamlAstResolver(compilation, context.ParseInformation); var mrr = resolver.ResolveAttribute(context.Attribute) as MemberResolveResult; IEvent evt; if (mrr == null || (evt = mrr.Member as IEvent) == null) { return(EmptyList <ICompletionItem> .Instance); } int offset = XmlEditor.XmlParser.GetActiveElementStartIndex(context.Editor.Document.Text, context.Editor.Caret.Offset); if (offset == -1) { return(Enumerable.Empty <ICompletionItem>()); } var loc = context.Editor.Document.GetLocation(offset); string name = context.ActiveElement.GetAttributeValue("Name"); if (string.IsNullOrEmpty(name)) { name = context.ActiveElement.GetAttributeValue(XamlConst.XamlNamespace, "Name"); } return(FindMatchingEventHandlers(context, evt, (string.IsNullOrEmpty(name) ? item.Name : name))); } return(EmptyList <ICompletionItem> .Instance); }
bool DoMarkupExtensionCompletion(XamlCompletionContext context) { if (context.Description == XamlContextDescription.InMarkupExtension && context.AttributeValue != null && !context.AttributeValue.IsString) { if (!XamlBindingOptions.UseExtensionCompletion) { return(false); } var completionList = generator.CreateMarkupExtensionCompletion(context) as XamlCompletionItemList; if (completionList == null) { return(false); } string word = context.Editor.GetWordBeforeCaretExtended(); if (context.PressedKey != '.' && context.PressedKey != '=' && !word.EndsWith(".", StringComparison.Ordinal) && completionList.PreselectionLength == 0) { completionList.PreselectionLength = word.Length; } var insightList = generator.CreateMarkupExtensionInsight(context); context.Editor.ShowInsightWindow(insightList); context.Editor.ShowCompletionWindow(completionList); return(completionList.Items.Any() || insightList.Any()); } return(false); }
IType ResolveTargetType(XamlCompletionContext context, out string typeName, out int dotIndex, bool isPropertyOrEventName = false) { string targetTypeValue; dotIndex = -1; if (isPropertyOrEventName && context.AttributeValue.IsString) { dotIndex = context.AttributeValue.StringValue.IndexOf('.'); } if (dotIndex > 0) { targetTypeValue = context.AttributeValue.StringValue.Substring(0, dotIndex); } else { string element; bool isExplicit; if (context.ParentElement.Name.EndsWith("Trigger", StringComparison.Ordinal)) { element = "Trigger"; } else { element = context.ParentElement.Name; } targetTypeValue = Utils.LookForTargetTypeValue(context, out isExplicit, element); } AttributeValue value = MarkupExtensionParser.ParseValue(targetTypeValue ?? string.Empty); return(resolver.ResolveAttributeValue(context, value, out typeName).Type); }
IList <ICompletionItem> CreatePropertyPathCompletion(XamlCompletionContext context) { bool isExplicit; IType typeName = GetType(context, out isExplicit); IList <ICompletionItem> list = new List <ICompletionItem>(); string value = context.ValueStartOffset > -1 ? context.RawAttributeValue.Substring(0, Math.Min(context.ValueStartOffset + 1, context.RawAttributeValue.Length)) : ""; if (value.EndsWithAny(']', ')')) { return(list); } var segments = PropertyPathParser.Parse(value).ToList(); int completionStart; bool isAtDot = false; IType propertyPathType = ResolvePropertyPath(segments, context, typeName, out completionStart); if (completionStart < segments.Count) { PropertyPathSegment seg = segments[completionStart]; switch (seg.Kind) { case SegmentKind.ControlChar: if (seg.Content == ".") { AddAttributes(propertyPathType, list, false); isAtDot = true; } break; case SegmentKind.AttachedProperty: AddAttributes(seg.Resolve(context, propertyPathType), list, false); isAtDot = seg.Content.Contains("."); break; case SegmentKind.PropertyOrType: AddAttributes(propertyPathType, list, false); isAtDot = true; break; } } else if (typeName != null) { AddAttributes(typeName, list, false); } if (!isAtDot) { foreach (var item in GetAllTypes(context)) { list.Add(item); } } return(list); }
public bool CtrlSpace(ITextEditor editor) { compilation = SD.ParserService.GetCompilationForFile(editor.FileName); resolver = new XamlResolver(compilation); XamlCompletionContext context = XamlContextResolver.ResolveCompletionContext(editor, ' '); context.Forced = true; return(CtrlSpace(editor, context)); }
IList <ICompletionItem> CreateAttributeList(XamlCompletionContext context, bool includeEvents) { if (context.ParseInformation == null) { return(EmptyList <ICompletionItem> .Instance); } AXmlElement lastElement = context.ActiveElement; IUnresolvedFile file = context.ParseInformation.UnresolvedFile; XamlResolver resolver = new XamlResolver(compilation); IType type = resolver.ResolveType(lastElement.Namespace, lastElement.LocalName.Trim('.')); var list = new List <ICompletionItem>(); string xamlPrefix = context.XamlNamespacePrefix; string xKey = string.IsNullOrEmpty(xamlPrefix) ? "" : xamlPrefix + ":"; if (lastElement.Prefix == context.XamlNamespacePrefix && XamlConst.IsBuiltin(lastElement.LocalName)) { return(EmptyList <ICompletionItem> .Instance); } if (lastElement.LocalName.EndsWith(".", StringComparison.OrdinalIgnoreCase) || context.PressedKey == '.') { if (type.Kind == TypeKind.Unknown) { return(EmptyList <ICompletionItem> .Instance); } if (context.ParentElement != null && context.ParentElement.LocalName.StartsWith(lastElement.LocalName.TrimEnd('.'), StringComparison.OrdinalIgnoreCase)) { AddAttributes(type, list, includeEvents); } AddAttachedProperties(type.GetDefinition(), list); } else { if (type.Kind == TypeKind.Unknown) { list.Add(new XamlCompletionItem(xKey + "Uid")); } else { AddAttributes(type, list, includeEvents); list.AddRange(GetListOfAttached(context, null, includeEvents, true)); list.AddRange( XamlConst.XamlNamespaceAttributes .Where(localName => XamlConst.IsAttributeAllowed(context.InRoot, localName)) .Select(item => new XamlCompletionItem(xKey + item)) ); } } return(list); }
bool CtrlSpace(ITextEditor editor, XamlCompletionContext context) { if (context.Description == XamlContextDescription.InComment || context.Description == XamlContextDescription.InCData || context.ActiveElement == null) { return(false); } if (!context.InAttributeValueOrMarkupExtension) { XamlCompletionItemList list = generator.CreateListForContext(context); string starter = editor.GetWordBeforeCaretExtended().TrimStart('/'); if (context.Description != XamlContextDescription.None && !string.IsNullOrEmpty(starter)) { if (starter.Contains(".")) { list.PreselectionLength = starter.Length - starter.IndexOf('.') - 1; } else { list.PreselectionLength = starter.Length; } } editor.ShowCompletionWindow(list); return(true); } // DO NOT USE generator.CreateListForContext here!!! results in endless recursion!!!! if (context.Attribute != null) { if (!DoMarkupExtensionCompletion(context)) { var completionList = new XamlCompletionItemList(context); completionList.PreselectionLength = editor.GetWordBeforeCaretExtended().Length; if ((context.ActiveElement.Name == "Setter" || context.ActiveElement.Name == "EventSetter") && (context.Attribute.Name == "Property" || context.Attribute.Name == "Value")) { DoSetterAndEventSetterCompletion(context, completionList); editor.ShowCompletionWindow(completionList); } else if ((context.ActiveElement.Name.EndsWith("Trigger", StringComparison.Ordinal) || context.ActiveElement.Name == "Condition") && context.Attribute.Name == "Value") { DoTriggerCompletion(context, completionList); editor.ShowCompletionWindow(completionList); } else if (!DoAttributeCompletion(context, completionList)) { DoXmlAttributeCompletion(context, completionList); } return(completionList.Items.Any()); } return(true); } return(false); }
static void DoTriggerCompletion(XamlCompletionContext context, XamlCompletionItemList completionList) { bool isExplicit; AttributeValue value = MarkupExtensionParser.ParseValue(CompletionDataHelper.LookForTargetTypeValue(context, out isExplicit, "Trigger") ?? string.Empty); IReturnType typeName = null; string typeNameString = null; if (!value.IsString) { typeNameString = CompletionDataHelper.GetTypeNameFromTypeExtension(value.ExtensionValue, context); typeName = CompletionDataHelper.ResolveType(typeNameString, context); } else { typeNameString = value.StringValue; typeName = CompletionDataHelper.ResolveType(value.StringValue, context); } if (typeName != null) { switch (context.Attribute.Name) { case "Value": AttributeValue propType = MarkupExtensionParser.ParseValue(context.ActiveElement.GetAttributeValue("Property") ?? ""); if (!propType.IsString) { break; } string name = propType.StringValue; if (!name.Contains(".")) { name = typeNameString + "." + name; } context.Description = XamlContextDescription.AtTag; var member = XamlResolver.Resolve(name, context) as MemberResolveResult; if (member == null || member.ResolvedMember == null) { break; } completionList.Items.AddRange( CompletionDataHelper.MemberCompletion(context, member.ResolvedMember.ReturnType, string.Empty) ); break; } } }
IEnumerable <ICompletionItem> GetAllTypes(XamlCompletionContext context) { var items = GetClassesFromContext(context); foreach (var ns in items) { foreach (var c in ns.Value) { if (c.Kind == TypeKind.Class && !c.IsDerivedFrom(KnownTypeCode.Attribute)) { yield return(new XamlCompletionItem(ns.Key, c)); } } } }
bool DoStaticExtensionCompletion(XamlCompletionItemList list, XamlCompletionContext context) { AttributeValue selItem = Utils.GetMarkupExtensionAtPosition(context.AttributeValue.ExtensionValue, context.ValueStartOffset) .PositionalArguments.LastOrDefault(); var resolver = new XamlResolver(compilation); if (context.PressedKey == '.') { if (selItem != null && selItem.IsString) { var rr = resolver.ResolveAttributeValue(selItem.StringValue, context) as TypeResolveResult; if (rr != null) { list.Items.AddRange(MemberCompletion(context, rr.Type, string.Empty)); } return(false); } } else { if (selItem != null && selItem.IsString) { int index = selItem.StringValue.IndexOf('.'); string s = (index > -1) ? selItem.StringValue.Substring(0, index) : selItem.StringValue; var rr = resolver.ResolveAttributeValue(s, context) as TypeResolveResult; if (rr != null && rr.Type.Kind != TypeKind.Unknown) { list.Items.AddRange(MemberCompletion(context, rr.Type, (index == -1) ? "." : string.Empty)); list.PreselectionLength = (index > -1) ? selItem.StringValue.Length - index - 1 : 0; return(false); } else { DoStaticTypeCompletion(selItem, list, context); } } else { DoStaticTypeCompletion(selItem, list, context); } } return(true); }
public IEnumerable <ICompletionItem> FindMatchingEventHandlers(XamlCompletionContext context, IEvent member, string targetName) { ITypeDefinition td = member.ReturnType.GetDefinition(); if (td == null) { yield break; } IMethod delegateInvoker = td.GetMethods(m => m.Name == "Invoke").FirstOrDefault(); if (delegateInvoker == null) { yield break; } if (context.ParseInformation == null) { yield break; } var file = context.ParseInformation.UnresolvedFile; var loc = context.Editor.Caret.Location; var unresolved = file.GetInnermostTypeDefinition(loc.Line, loc.Column); if (unresolved == null) { yield break; } IType type = unresolved.Resolve(new SimpleTypeResolveContext(compilation.MainAssembly)).GetDefinition(); foreach (IMethod method in type.GetMethods(m => m.Parameters.Count == delegateInvoker.Parameters.Count)) { if (!method.ReturnType.Equals(delegateInvoker.ReturnType)) { continue; } if (method.Parameters.SequenceEqual(delegateInvoker.Parameters, new ParameterComparer())) { yield return(new XamlCompletionItem(method)); } } yield return(new NewEventCompletionItem(member, targetName)); }
public static IType Resolve(this PropertyPathSegment segment, XamlCompletionContext context, IType previousType) { if (segment.Kind == SegmentKind.SourceTraversal) { return(previousType); } if (segment.Kind == SegmentKind.ControlChar) { return(previousType); } string content = segment.Content; if (segment.Kind == SegmentKind.AttachedProperty && content.StartsWith("(", StringComparison.Ordinal)) { content = content.TrimStart('('); if (content.Contains(".")) { content = content.Remove(content.IndexOf('.')); } } ICompilation compilation = SD.ParserService.GetCompilationForFile(context.Editor.FileName); XamlResolver resolver = new XamlResolver(compilation); ResolveResult rr = resolver.ResolveExpression(content, context); IType type = rr.Type; if (previousType != null) { IMember member = previousType.GetMemberByName(content); if (member != null) { type = member.ReturnType; } } else if (rr is MemberResolveResult) { MemberResolveResult mrr = rr as MemberResolveResult; if (mrr.Member != null) { type = mrr.Member.ReturnType; } } return(type); }
public static XamlCompletionContext ResolveCompletionContext(ITextEditor editor, char typedValue, int offset) { var binding = editor.GetService(typeof(XamlTextEditorExtension)) as XamlTextEditorExtension; if (binding == null) { throw new InvalidOperationException("Can only use ResolveCompletionContext with a XamlTextEditorExtension."); } var context = new XamlCompletionContext(ResolveContext(editor.FileName, editor.Document, offset)) { PressedKey = typedValue, Editor = editor }; return(context); }
/// <remarks>returns true if elements from named args completion should be added afterwards.</remarks> bool DoPositionalArgsCompletion(XamlCompletionItemList list, XamlCompletionContext context, MarkupExtensionInfo markup, IType type) { switch (type.FullName) { 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) { return(DoStaticExtensionCompletion(list, context)); } break; case "System.Windows.Markup.TypeExtension": if (context.AttributeValue.ExtensionValue.PositionalArguments.Count <= 1) { list.Items.AddRange(GetClassesFromContext(context).FlattenToList()); AttributeValue selItem = Utils.GetMarkupExtensionAtPosition(context.AttributeValue.ExtensionValue, context.ValueStartOffset) .PositionalArguments.LastOrDefault(); string word = context.Editor.GetWordBeforeCaret().TrimEnd(); if (selItem != null && selItem.IsString && word == selItem.StringValue) { list.PreselectionLength = selItem.StringValue.Length; } } break; default: var ctors = type.GetMethods(m => m.IsPublic && m.IsConstructor && m.Parameters.Count >= markup.PositionalArguments.Count + 1); if (context.Forced) { return(true); } if (ctors.Any() || markup.PositionalArguments.Count == 0) { return(false); } break; } return(true); }
public IEnumerable <IInsightItem> CreateMarkupExtensionInsight(XamlCompletionContext context) { var markup = Utils.GetMarkupExtensionAtPosition(context.AttributeValue.ExtensionValue, context.ValueStartOffset); var resolver = new XamlResolver(compilation); var type = (resolver.ResolveExpression(markup.ExtensionType, context) ?? resolver.ResolveExpression(markup.ExtensionType + "Extension", context)).Type; if (type != null) { var ctors = type .GetMethods(m => m.IsPublic && m.IsConstructor && m.Parameters.Count >= markup.PositionalArguments.Count) .OrderBy(m => m.Parameters.Count); foreach (var ctor in ctors) { yield return(new MarkupExtensionInsightItem(ctor)); } } }
static IType ResolvePropertyPath(IList <PropertyPathSegment> segments, XamlCompletionContext context, IType parentType, out int lastIndex) { IType type = parentType; for (lastIndex = 0; lastIndex < segments.Count - 1; lastIndex++) { PropertyPathSegment segment = segments[lastIndex]; switch (segment.Kind) { case SegmentKind.AttachedProperty: // do we need to take account of previous results? type = segment.Resolve(context, null); break; case SegmentKind.ControlChar: if (segment.Content == "[" || segment.Content == "(" || segment.Content == "/") { return(null); } return(type); case SegmentKind.PropertyOrType: type = segment.Resolve(context, type); break; case SegmentKind.Indexer: if (type != null) { IProperty prop = type.GetProperties(p => p.IsIndexer).FirstOrDefault(); if (prop != null) { type = prop.ReturnType; } } break; case SegmentKind.SourceTraversal: // ignore return(null); } } return(type); }
public ICompletionItemList CreateMarkupExtensionCompletion(XamlCompletionContext context) { var list = new XamlCompletionItemList(context); compilation = SD.ParserService.GetCompilationForFile(context.Editor.FileName); string visibleValue = context.RawAttributeValue.Substring(0, Utils.MinMax(context.ValueStartOffset, 0, context.RawAttributeValue.Length)); if (context.PressedKey == '=') { visibleValue += "="; } var markup = Utils.GetMarkupExtensionAtPosition(context.AttributeValue.ExtensionValue, context.ValueStartOffset); var resolver = new XamlResolver(compilation); var type = resolver.ResolveExpression(markup.ExtensionType, context).Type; if (type.Kind == TypeKind.Unknown) { type = resolver.ResolveExpression(markup.ExtensionType + "Extension", context).Type; } if (type.Kind == TypeKind.Unknown) { list.Items.AddRange(CreateListOfMarkupExtensions(context)); list.PreselectionLength = markup.ExtensionType.Length; } else { if (markup.NamedArguments.Count == 0) { if (DoPositionalArgsCompletion(list, context, markup, type)) { DoNamedArgsCompletion(list, context, type, markup); } } else { DoNamedArgsCompletion(list, context, type, markup); } } list.SortItems(); return(list); }
public static MemberResolveResult ResolveMember(string expression, XamlCompletionContext context) { if (context.ParseInformation == null || string.IsNullOrEmpty(context.Editor.Document.Text)) { return(null); } var expressionResult = new ExpressionResult(expression, context); XamlResolver resolver = new XamlResolver(); resolver.resolveExpression = expression; resolver.caretLine = expressionResult.Region.BeginLine; resolver.caretColumn = expressionResult.Region.BeginColumn; resolver.callingClass = context.ParseInformation.CompilationUnit.GetInnermostClass(resolver.caretLine, resolver.caretColumn); resolver.context = context; return(resolver.ResolveNamedAttribute(expression)); }
void DoTriggerCompletion(XamlCompletionContext context, XamlCompletionItemList completionList) { bool isExplicit; AttributeValue value = MarkupExtensionParser.ParseValue(Utils.LookForTargetTypeValue(context, out isExplicit, "Trigger") ?? string.Empty); string typeNameString; var rr = resolver.ResolveAttributeValue(context, value, out typeNameString); var typeName = rr.Type; if (typeName != null) { switch (context.Attribute.Name) { case "Value": AttributeValue propType = MarkupExtensionParser.ParseValue(context.ActiveElement.GetAttributeValue("Property") ?? ""); if (!propType.IsString) { break; } string name = propType.StringValue; if (!name.Contains(".")) { name = typeNameString + "." + name; } context.Description = XamlContextDescription.AtTag; var mrr = resolver.ResolveExpression(name, context) as MemberResolveResult; if (mrr == null || mrr.Member == null) { break; } completionList.Items.AddRange( generator.MemberCompletion(context, mrr.Member.ReturnType, string.Empty) ); break; } } }
static bool CreateEventHandlerCode(XamlCompletionContext context, NewEventCompletionItem completionItem) { IProject project = SD.ProjectService.FindProjectContainingFile(context.Editor.FileName); if (project == null) { return(false); } var unresolved = context.ParseInformation.UnresolvedFile.TypeDefinition; if (unresolved == null) { return(false); } var compilation = SD.ParserService.GetCompilationForFile(context.Editor.FileName); var definition = unresolved.Resolve(new SimpleTypeResolveContext(compilation.MainAssembly)).GetDefinition(); project.LanguageBinding.CodeGenerator.InsertEventHandler(definition, completionItem.HandlerName, completionItem.EventType, true); return(true); }
void DoXmlAttributeCompletion(XamlCompletionContext context, XamlCompletionItemList completionList) { if (context.Attribute.Name == "xml:space") { completionList.Items.AddRange(new[] { new XamlCompletionItem("preserve"), new XamlCompletionItem("default") }); } if (context.Attribute.Prefix.Equals("xmlns", StringComparison.OrdinalIgnoreCase) || context.Attribute.Name.Equals("xmlns", StringComparison.OrdinalIgnoreCase)) { completionList.Items.AddRange(generator.CreateListForXmlnsCompletion(compilation)); ICompletionListWindow window = context.Editor.ShowCompletionWindow(completionList); if (window != null) { window.Width = 400; } } }
void DoNamedArgsCompletion(XamlCompletionItemList list, XamlCompletionContext context, IType type, MarkupExtensionInfo markup) { if (markup.NamedArguments.Count > 0 && !context.Editor.GetWordBeforeCaret().StartsWith(",", StringComparison.OrdinalIgnoreCase)) { int lastStart = markup.NamedArguments.Max(i => i.Value.StartOffset); var item = markup.NamedArguments.First(p => p.Value.StartOffset == lastStart); if (context.RawAttributeValue.EndsWith("=", StringComparison.OrdinalIgnoreCase) || (item.Value.IsString && item.Value.StringValue.EndsWith(context.Editor.GetWordBeforeCaretExtended(), StringComparison.Ordinal))) { var resolver = new XamlResolver(compilation); MemberResolveResult mrr = resolver.ResolveAttributeValue(item.Key, context) as MemberResolveResult; if (mrr != null && mrr.Member != null && mrr.Member.ReturnType != null) { IType memberType = mrr.Member.ReturnType; list.Items.AddRange(MemberCompletion(context, memberType, string.Empty)); } return; } } list.Items.AddRange(type.GetProperties().Where(p => p.CanSet && p.IsPublic).Select(p => new XamlCompletionItem(p.Name + "=", p))); }
bool DoAttributeCompletion(XamlCompletionContext context, XamlCompletionItemList completionList) { XamlAstResolver resolver = new XamlAstResolver(compilation, context.ParseInformation); ITextEditor editor = context.Editor; var mrr = resolver.ResolveAttribute(context.Attribute) as MemberResolveResult; if (mrr != null && mrr.Type.Kind != TypeKind.Unknown) { completionList.Items.AddRange(generator.MemberCompletion(context, mrr.Type, string.Empty)); editor.ShowInsightWindow(generator.MemberInsight(mrr)); editor.ShowCompletionWindow(completionList); switch (mrr.Type.FullName) { case "System.Windows.PropertyPath": string start = editor.GetWordBeforeCaretExtended(); int index = start.LastIndexOfAny(PropertyPathTokenizer.ControlChars); if (index + 1 < start.Length) { start = start.Substring(index + 1); } else { start = ""; } completionList.PreselectionLength = start.Length; break; case "System.Windows.Media.FontFamily": string text = context.ValueStartOffset > -1 ? context.RawAttributeValue.Substring(0, Math.Min(context.ValueStartOffset, context.RawAttributeValue.Length)) : ""; int lastComma = text.LastIndexOf(','); completionList.PreselectionLength = lastComma == -1 ? context.ValueStartOffset : context.ValueStartOffset - lastComma - 1; break; } } return(completionList.Items.Any()); }
public IEnumerable <ICompletionItem> CreateListOfMarkupExtensions(XamlCompletionContext context) { var markupExtensionType = compilation.FindType(typeof(System.Windows.Markup.MarkupExtension)) .GetDefinition(); if (markupExtensionType == null) { yield break; } string text; foreach (var ns in GetClassesFromContext(context)) { foreach (var definition in ns.Value.Where(td => td.IsDerivedFrom(markupExtensionType))) { text = definition.Name; if (text.EndsWith("Extension", StringComparison.Ordinal)) { text = text.Remove(text.Length - "Extension".Length); } string prefix = ns.Key; if (prefix.Length > 0) { text = prefix + ":" + text; } yield return(new XamlCompletionItem(text, definition)); } } text = "Reference"; if (context.XamlNamespacePrefix != "") { text = context.XamlNamespacePrefix + ":" + text; } yield return(new XamlCompletionItem(text)); }
bool CtrlSpace(ITextEditor editor, XamlCompletionContext context) { if (context.Description == XamlContextDescription.InComment || context.Description == XamlContextDescription.InCData || context.ActiveElement == null) { return false; } if (!context.InAttributeValueOrMarkupExtension) { XamlCompletionItemList list = generator.CreateListForContext(context); string starter = editor.GetWordBeforeCaretExtended().TrimStart('/'); if (context.Description != XamlContextDescription.None && !string.IsNullOrEmpty(starter)) { if (starter.Contains(".")) { list.PreselectionLength = starter.Length - starter.IndexOf('.') - 1; } else { list.PreselectionLength = starter.Length; } } editor.ShowCompletionWindow(list); return true; } // DO NOT USE generator.CreateListForContext here!!! results in endless recursion!!!! if (context.Attribute != null) { if (!DoMarkupExtensionCompletion(context)) { var completionList = new XamlCompletionItemList(context); completionList.PreselectionLength = editor.GetWordBeforeCaretExtended().Length; if ((context.ActiveElement.Name == "Setter" || context.ActiveElement.Name == "EventSetter") && (context.Attribute.Name == "Property" || context.Attribute.Name == "Value")) { DoSetterAndEventSetterCompletion(context, completionList); editor.ShowCompletionWindow(completionList); } else if ((context.ActiveElement.Name.EndsWith("Trigger", StringComparison.Ordinal) || context.ActiveElement.Name == "Condition") && context.Attribute.Name == "Value") { DoTriggerCompletion(context, completionList); editor.ShowCompletionWindow(completionList); } else if (!DoAttributeCompletion(context, completionList)) { DoXmlAttributeCompletion(context, completionList); } return completionList.Items.Any(); } return true; } return false; }
public static XamlCompletionContext ResolveCompletionContext(ITextEditor editor, char typedValue, int offset) { var binding = editor.GetService(typeof(XamlTextEditorExtension)) as XamlTextEditorExtension; if (binding == null) throw new InvalidOperationException("Can only use ResolveCompletionContext with a XamlTextEditorExtension."); var context = new XamlCompletionContext(ResolveContext(editor.FileName, editor.Document, offset)) { PressedKey = typedValue, Editor = editor }; return context; }
IEnumerable<ICompletionItem> GetAllTypes(XamlCompletionContext context) { var items = GetClassesFromContext(context); foreach (var ns in items) { foreach (var c in ns.Value) { if (c.Kind == TypeKind.Class && !c.IsDerivedFrom(KnownTypeCode.Attribute)) yield return new XamlCompletionItem(ns.Key, c); } } }
IEnumerable<ICompletionItem> CreateEventCompletion(XamlCompletionContext context, ITypeDefinition td) { IMethod invoker = td.GetMethods(method => method.Name == "Invoke").FirstOrDefault(); if (invoker != null && context.ActiveElement != null) { var item = context.ActiveElement; var resolver = new XamlAstResolver(compilation, context.ParseInformation); var mrr = resolver.ResolveAttribute(context.Attribute) as MemberResolveResult; IEvent evt; if (mrr == null || (evt = mrr.Member as IEvent) == null) return EmptyList<ICompletionItem>.Instance; int offset = XmlEditor.XmlParser.GetActiveElementStartIndex(context.Editor.Document.Text, context.Editor.Caret.Offset); if (offset == -1) return Enumerable.Empty<ICompletionItem>(); var loc = context.Editor.Document.GetLocation(offset); string name = context.ActiveElement.GetAttributeValue("Name"); if (string.IsNullOrEmpty(name)) name = context.ActiveElement.GetAttributeValue(XamlConst.XamlNamespace, "Name"); return FindMatchingEventHandlers(context, evt, (string.IsNullOrEmpty(name) ? item.Name : name)); } return EmptyList<ICompletionItem>.Instance; }
public IEnumerable<ICompletionItem> CreateListOfMarkupExtensions(XamlCompletionContext context) { var markupExtensionType = compilation.FindType(typeof(System.Windows.Markup.MarkupExtension)) .GetDefinition(); if (markupExtensionType == null) yield break; string text; foreach (var ns in GetClassesFromContext(context)) { foreach (var definition in ns.Value.Where(td => td.IsDerivedFrom(markupExtensionType))) { text = definition.Name; if (text.EndsWith("Extension", StringComparison.Ordinal)) text = text.Remove(text.Length - "Extension".Length); string prefix = ns.Key; if (prefix.Length > 0) { text = prefix + ":" + text; } yield return new XamlCompletionItem(text, definition); } } text = "Reference"; if (context.XamlNamespacePrefix != "") { text = context.XamlNamespacePrefix + ":" + text; } yield return new XamlCompletionItem(text); }
bool DoStaticExtensionCompletion(XamlCompletionItemList list, XamlCompletionContext context) { AttributeValue selItem = Utils.GetMarkupExtensionAtPosition(context.AttributeValue.ExtensionValue, context.ValueStartOffset) .PositionalArguments.LastOrDefault(); var resolver = new XamlResolver(compilation); if (context.PressedKey == '.') { if (selItem != null && selItem.IsString) { var rr = resolver.ResolveAttributeValue(selItem.StringValue, context) as TypeResolveResult; if (rr != null) list.Items.AddRange(MemberCompletion(context, rr.Type, string.Empty)); return false; } } else { if (selItem != null && selItem.IsString) { int index = selItem.StringValue.IndexOf('.'); string s = (index > -1) ? selItem.StringValue.Substring(0, index) : selItem.StringValue; var rr = resolver.ResolveAttributeValue(s, context) as TypeResolveResult; if (rr != null && rr.Type.Kind != TypeKind.Unknown) { list.Items.AddRange(MemberCompletion(context, rr.Type, (index == -1) ? "." : string.Empty)); list.PreselectionLength = (index > -1) ? selItem.StringValue.Length - index - 1 : 0; return false; } else DoStaticTypeCompletion(selItem, list, context); } else { DoStaticTypeCompletion(selItem, list, context); } } return true; }
static void DoTriggerCompletion(XamlCompletionContext context, XamlCompletionItemList completionList) { bool isExplicit; AttributeValue value = MarkupExtensionParser.ParseValue(CompletionDataHelper.LookForTargetTypeValue(context, out isExplicit, "Trigger") ?? string.Empty); IReturnType typeName = null; string typeNameString = null; if (!value.IsString) { typeNameString = CompletionDataHelper.GetTypeNameFromTypeExtension(value.ExtensionValue, context); typeName = CompletionDataHelper.ResolveType(typeNameString, context); } else { typeNameString = value.StringValue; typeName = CompletionDataHelper.ResolveType(value.StringValue, context); } if (typeName != null) { switch (context.Attribute.Name) { case "Value": AttributeValue propType = MarkupExtensionParser.ParseValue(context.ActiveElement.GetAttributeValue("Property") ?? ""); if (!propType.IsString) break; string name = propType.StringValue; if (!name.Contains(".")) name = typeNameString + "." + name; context.Description = XamlContextDescription.AtTag; var member = XamlResolver.Resolve(name, context) as MemberResolveResult; if (member == null || member.ResolvedMember == null) break; completionList.Items.AddRange( CompletionDataHelper.MemberCompletion(context, member.ResolvedMember.ReturnType, string.Empty) ); break; } } }
public ICompletionItemList CreateMarkupExtensionCompletion(XamlCompletionContext context) { var list = new XamlCompletionItemList(context); compilation = SD.ParserService.GetCompilationForFile(context.Editor.FileName); string visibleValue = context.RawAttributeValue.Substring(0, Utils.MinMax(context.ValueStartOffset, 0, context.RawAttributeValue.Length)); if (context.PressedKey == '=') visibleValue += "="; var markup = Utils.GetMarkupExtensionAtPosition(context.AttributeValue.ExtensionValue, context.ValueStartOffset); var resolver = new XamlResolver(compilation); var type = resolver.ResolveExpression(markup.ExtensionType, context).Type; if (type.Kind == TypeKind.Unknown) type = resolver.ResolveExpression(markup.ExtensionType + "Extension", context).Type; if (type.Kind == TypeKind.Unknown) { list.Items.AddRange(CreateListOfMarkupExtensions(context)); list.PreselectionLength = markup.ExtensionType.Length; } else { if (markup.NamedArguments.Count == 0) { if (DoPositionalArgsCompletion(list, context, markup, type)) DoNamedArgsCompletion(list, context, type, markup); } else DoNamedArgsCompletion(list, context, type, markup); } list.SortItems(); return list; }
void DoStaticTypeCompletion(AttributeValue selItem, XamlCompletionItemList list, XamlCompletionContext context) { var items = GetClassesFromContext(context); foreach (var ns in items) { string key = ns.Key; if (!string.IsNullOrEmpty(key)) { key += ":"; } list.Items.AddRange( ns.Value .Where(c => c.Fields.Any(f => f.IsStatic) || c.Properties.Any(p => p.IsStatic)) .Select(c => new XamlCompletionItem(key + c.Name, c)) ); } if (selItem != null && selItem.IsString) { list.PreselectionLength = selItem.StringValue.Length; } }
public static ResolveResult Resolve(string expression, XamlCompletionContext context) { return(new XamlResolver().Resolve(new ExpressionResult(expression, context), context.ParseInformation, null)); }
public static ResolveResult Resolve(string expression, XamlCompletionContext context) { return new XamlResolver().Resolve(new ExpressionResult(expression, context), context.ParseInformation, null); }
public static MemberResolveResult ResolveMember(string expression, XamlCompletionContext context) { if (context.ParseInformation == null || string.IsNullOrEmpty(context.Editor.Document.Text)) return null; var expressionResult = new ExpressionResult(expression, context); XamlResolver resolver = new XamlResolver(); resolver.resolveExpression = expression; resolver.caretLine = expressionResult.Region.BeginLine; resolver.caretColumn = expressionResult.Region.BeginColumn; resolver.callingClass = context.ParseInformation.CompilationUnit.GetInnermostClass(resolver.caretLine, resolver.caretColumn); resolver.context = context; return resolver.ResolveNamedAttribute(expression); }
void DoSetterAndEventSetterCompletion(XamlCompletionContext context, XamlCompletionItemList completionList) { bool isExplicit; string element = context.ParentElement.Name.EndsWith("Trigger", StringComparison.Ordinal) ? "Trigger" : context.ParentElement.Name; AttributeValue value = MarkupExtensionParser.ParseValue(Utils.LookForTargetTypeValue(context, out isExplicit, element) ?? string.Empty); string typeNameString; var rr = resolver.ResolveAttributeValue(context, value, out typeNameString); IType typeName = rr.Type; MemberResolveResult mrr; switch (context.Attribute.Name) { case "Value": AttributeValue propType = MarkupExtensionParser.ParseValue(context.ActiveElement.GetAttributeValue("Property") ?? ""); if (!propType.IsString) break; context.Description = XamlContextDescription.AtTag; string name = propType.StringValue; if (!name.Contains(".")) name = typeNameString + "." + name; mrr = resolver.ResolveExpression(name, context) as MemberResolveResult; if (mrr == null || mrr.Member == null) break; completionList.Items.AddRange( generator.MemberCompletion(context, mrr.Member.ReturnType, string.Empty) ); break; case "Property": completionList.Items.AddRange( typeName.GetProperties() .Where(p => p.IsPublic && p.CanSet) .Select(prop => new XamlCompletionItem(prop)) ); break; case "Event": completionList.Items.AddRange( typeName.GetEvents() .Where(e => e.IsPublic) .Select(evt => new XamlCompletionItem(evt)) ); break; case "Handler": var loc3 = context.Editor.Document.GetLocation(XmlParser.GetActiveElementStartIndex(context.Editor.Document.Text, context.Editor.Caret.Offset)); AttributeValue evtType = MarkupExtensionParser.ParseValue(context.ActiveElement.GetAttributeValue("Event") ?? ""); if (!evtType.IsString) break; string evtName = evtType.StringValue; if (!evtName.Contains(".")) evtName = typeNameString + "." + evtName; mrr = resolver.ResolveExpression(evtName, context) as MemberResolveResult; if (mrr == null) break; var member = mrr.Member as IEvent; if (member == null) break; completionList.Items.AddRange(generator.FindMatchingEventHandlers(context, member, typeName.Name)); break; } }
static void DoSetterAndEventSetterCompletion(XamlCompletionContext context, XamlCompletionItemList completionList) { bool isExplicit; string element = context.ParentElement.Name.EndsWith("Trigger") ? "Trigger" : context.ParentElement.Name; AttributeValue value = MarkupExtensionParser.ParseValue(CompletionDataHelper.LookForTargetTypeValue(context, out isExplicit, element) ?? string.Empty); IReturnType typeName = null; string typeNameString = null; if (!value.IsString) { typeNameString = CompletionDataHelper.GetTypeNameFromTypeExtension(value.ExtensionValue, context); typeName = CompletionDataHelper.ResolveType(typeNameString, context); } else { typeNameString = value.StringValue; typeName = CompletionDataHelper.ResolveType(value.StringValue, context); } if (typeName != null) { switch (context.Attribute.Name) { case "Value": AttributeValue propType = MarkupExtensionParser.ParseValue(context.ActiveElement.GetAttributeValue("Property") ?? ""); if (!propType.IsString) break; context.Description = XamlContextDescription.AtTag; string name = propType.StringValue; if (!name.Contains(".")) name = typeNameString + "." + name; var member = XamlResolver.Resolve(name, context) 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 XamlCodeCompletionItem(prop)) ); break; case "Event": completionList.Items.AddRange( typeName.GetEvents() .Where(e => e.IsPublic) .Select(evt => new XamlCodeCompletionItem(evt)) ); break; case "Handler": var loc3 = context.Editor.Document.OffsetToPosition(XmlParser.GetActiveElementStartIndex(context.Editor.Document.Text, context.Editor.Caret.Offset)); AttributeValue evtType = MarkupExtensionParser.ParseValue(context.ActiveElement.GetAttributeValue("Event") ?? ""); if (!evtType.IsString) break; string evtName = evtType.StringValue; if (!evtName.Contains(".")) evtName = typeNameString + "." + evtName; var evtMember = XamlResolver.Resolve(evtName, context) as MemberResolveResult; if (evtMember == null || evtMember.ResolvedMember == null || !(evtMember.ResolvedMember is IEvent) || evtMember.ResolvedMember.ReturnType == null) break; IClass c = (evtMember.ResolvedMember as IEvent).ReturnType.GetUnderlyingClass(); if (c == null) break; IMethod invoker = c.Methods.FirstOrDefault(m => m.Name == "Invoke"); if (invoker == null) break; completionList.Items.AddRange( CompletionDataHelper.AddMatchingEventHandlers(context, invoker).Add(new NewEventCompletionItem(evtMember.ResolvedMember as IEvent, typeName.Name)) ); break; } } }
public XamlCompletionItemList CreateListForContext(XamlCompletionContext context) { XamlCompletionItemList list = new XamlCompletionItemList(context); ITextEditor editor = context.Editor; compilation = SD.ParserService.GetCompilationForFile(editor.FileName); XamlAstResolver resolver = new XamlAstResolver(compilation, context.ParseInformation); switch (context.Description) { case XamlContextDescription.None: if (context.Forced) { list.Items.AddRange(standardElements); list.Items.AddRange(CreateElementList(context, false)); AddClosingTagCompletion(context, list, resolver); } break; case XamlContextDescription.AtTag: if ((editor.Caret.Offset > 0 && editor.Document.GetCharAt(editor.Caret.Offset - 1) == '.') || context.PressedKey == '.') { list.Items.AddRange(CreateAttributeList(context, false)); } else { list.Items.AddRange(standardElements); list.Items.AddRange(CreateElementList(context, false)); AddClosingTagCompletion(context, list, resolver); } break; case XamlContextDescription.InTag: string word = editor.GetWordBeforeCaretExtended(); if (context.PressedKey == '.' || word.Contains(".")) { int pos = word.IndexOf(':'); string element = word.Substring(pos + 1, word.Length - pos - 1); string className = word; int propertyStart = element.IndexOf('.'); if (propertyStart != -1) { element = element.Substring(0, propertyStart).TrimEnd('.'); className = className.Substring(0, propertyStart + pos + 1).TrimEnd('.'); } int caretOffset = editor.Caret.Offset; int offset = editor.Document.LastIndexOf(className, caretOffset - word.Length, word.Length, StringComparison.OrdinalIgnoreCase); TextLocation loc = editor.Document.GetLocation(offset); XamlFullParseInformation info = context.ParseInformation; XamlResolver nameResolver = new XamlResolver(compilation); TypeResolveResult trr = nameResolver.ResolveExpression(className, context) as TypeResolveResult; ITypeDefinition typeClass = trr != null ? trr.Type.GetDefinition() : null; if (typeClass != null && typeClass.HasAttached(true, true)) list.Items.AddRange(GetListOfAttached(context, typeClass, true, true)); } else { list.Items.AddRange(CreateAttributeList(context, true)); list.Items.AddRange(standardAttributes); } break; case XamlContextDescription.InAttributeValue: new XamlCodeCompletionBinding().CtrlSpace(editor); break; } list.SortItems(); return list; }
public CodeCompletionKeyPressResult HandleKeyPress(ITextEditor editor, char ch) { XamlCompletionContext context = CompletionDataHelper.ResolveCompletionContext(editor, ch); XamlCompletionItemList list; if (context.Description == XamlContextDescription.InComment || context.Description == XamlContextDescription.InCData) { return(CodeCompletionKeyPressResult.None); } switch (ch) { case '<': context.Description = (context.Description == XamlContextDescription.None) ? XamlContextDescription.AtTag : context.Description; list = CompletionDataHelper.CreateListForContext(context); editor.ShowCompletionWindow(list); return(CodeCompletionKeyPressResult.Completed); case '>': return(CodeCompletionKeyPressResult.None); case '\'': case '"': if (!XmlParser.IsInsideAttributeValue(editor.Document.Text, editor.Caret.Offset)) { // count all " or ' chars before the next > char int search = editor.Caret.Offset + 1; int endMarkerCount = 1; char curCh = editor.Document.GetCharAt(search); while (search < editor.Document.TextLength - 1 && curCh != '>') { if (curCh == ch) { endMarkerCount++; } search++; curCh = editor.Document.GetCharAt(search); } // if the count is odd we need to add an additional " or ' char if (endMarkerCount % 2 != 0) { editor.Document.Insert(editor.Caret.Offset, ch.ToString()); editor.Caret.Offset--; this.CtrlSpace(editor); return(CodeCompletionKeyPressResult.Completed); } } break; case '{': // starting point for Markup Extension Completion if (context.Attribute != null && XmlParser.IsInsideAttributeValue(editor.Document.Text, editor.Caret.Offset) && !(context.RawAttributeValue.StartsWith("{}", StringComparison.OrdinalIgnoreCase) && context.RawAttributeValue.Length != 2)) { if (editor.SelectionLength != 0) { editor.Document.Remove(editor.SelectionStart, editor.SelectionLength); } editor.Document.Insert(editor.Caret.Offset, "{}"); editor.Caret.Offset--; this.CtrlSpace(editor); return(CodeCompletionKeyPressResult.EatKey); } break; case '.': switch (context.Description) { case XamlContextDescription.AtTag: case XamlContextDescription.InTag: if (context.ActiveElement != null && !XmlParser.IsInsideAttributeValue(editor.Document.Text, editor.Caret.Offset)) { list = CompletionDataHelper.CreateListForContext(context); editor.ShowCompletionWindow(list); return(CodeCompletionKeyPressResult.Completed); } break; case XamlContextDescription.InMarkupExtension: if (DoMarkupExtensionCompletion(context)) { return(CodeCompletionKeyPressResult.Completed); } break; case XamlContextDescription.InAttributeValue: if (editor.SelectionLength != 0) { editor.Document.Remove(editor.SelectionStart, editor.SelectionLength); } editor.Document.Insert(editor.Caret.Offset, "."); this.CtrlSpace(editor); return(CodeCompletionKeyPressResult.EatKey); } break; case '(': case '[': if (context.Description == XamlContextDescription.InAttributeValue) { if (editor.SelectionLength != 0) { editor.Document.Remove(editor.SelectionStart, editor.SelectionLength); } if (ch == '(') { editor.Document.Insert(editor.Caret.Offset, "()"); } if (ch == '[') { editor.Document.Insert(editor.Caret.Offset, "[]"); } editor.Caret.Offset--; this.CtrlSpace(editor); return(CodeCompletionKeyPressResult.EatKey); } break; case ':': if (context.ActiveElement != null && XmlParser.GetQualifiedAttributeNameAtIndex(editor.Document.Text, editor.Caret.Offset) == null) { if (context.Attribute != null && !context.Attribute.Name.StartsWith("xmlns", StringComparison.OrdinalIgnoreCase)) { list = CompletionDataHelper.CreateListForContext(context); list.PreselectionLength = editor.GetWordBeforeCaretExtended().Length; editor.ShowCompletionWindow(list); return(CodeCompletionKeyPressResult.CompletedIncludeKeyInCompletion); } } break; case '/': // ignore '/' when trying to type '/>' return(CodeCompletionKeyPressResult.None); case '=': if (!XmlParser.IsInsideAttributeValue(editor.Document.Text, editor.Caret.Offset)) { int searchOffset = editor.Caret.Offset; if (editor.SelectionLength != 0) { editor.Document.Remove(editor.SelectionStart, editor.SelectionLength); } while (searchOffset < editor.Document.TextLength - 1) { searchOffset++; if (!char.IsWhiteSpace(editor.Document.GetCharAt(searchOffset))) { break; } } if (searchOffset >= editor.Document.TextLength || editor.Document.GetCharAt(searchOffset) != '"') { 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); } else { DoMarkupExtensionCompletion(context); return(CodeCompletionKeyPressResult.Completed); } default: if (context.Description != XamlContextDescription.None && !char.IsWhiteSpace(ch)) { string starter = editor.GetWordBeforeCaretExtended(); if (!string.IsNullOrEmpty(starter)) { return(CodeCompletionKeyPressResult.None); } trackForced = false; string attributeName = (context.Attribute != null) ? context.Attribute.Name : string.Empty; if (!attributeName.StartsWith("xmlns", StringComparison.OrdinalIgnoreCase)) { return(this.CtrlSpace(editor) ? CodeCompletionKeyPressResult.CompletedIncludeKeyInCompletion : CodeCompletionKeyPressResult.None); } trackForced = true; return(CodeCompletionKeyPressResult.None); } break; } return(CodeCompletionKeyPressResult.None); }
/// <remarks>returns true if elements from named args completion should be added afterwards.</remarks> bool DoPositionalArgsCompletion(XamlCompletionItemList list, XamlCompletionContext context, MarkupExtensionInfo markup, IType type) { switch (type.FullName) { 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) return DoStaticExtensionCompletion(list, context); break; case "System.Windows.Markup.TypeExtension": if (context.AttributeValue.ExtensionValue.PositionalArguments.Count <= 1) { list.Items.AddRange(GetClassesFromContext(context).FlattenToList()); AttributeValue selItem = Utils.GetMarkupExtensionAtPosition(context.AttributeValue.ExtensionValue, context.ValueStartOffset) .PositionalArguments.LastOrDefault(); string word = context.Editor.GetWordBeforeCaret().TrimEnd(); if (selItem != null && selItem.IsString && word == selItem.StringValue) { list.PreselectionLength = selItem.StringValue.Length; } } break; default: var ctors = type.GetMethods(m => m.IsPublic && m.IsConstructor && m.Parameters.Count >= markup.PositionalArguments.Count + 1); if (context.Forced) return true; if (ctors.Any() || markup.PositionalArguments.Count == 0) return false; break; } return true; }
public bool CtrlSpace(ITextEditor editor) { XamlCompletionContext context = CompletionDataHelper.ResolveCompletionContext(editor, ' '); context.Forced = trackForced; if (context.Description == XamlContextDescription.InComment || context.Description == XamlContextDescription.InCData) { return(false); } if (context.ActiveElement != null) { if (!XmlParser.IsInsideAttributeValue(editor.Document.Text, editor.Caret.Offset) && context.Description != XamlContextDescription.InAttributeValue) { XamlCompletionItemList list = CompletionDataHelper.CreateListForContext(context); string starter = editor.GetWordBeforeCaretExtended().TrimStart('/'); if (context.Description != XamlContextDescription.None && !string.IsNullOrEmpty(starter)) { if (starter.Contains(".")) { list.PreselectionLength = starter.Length - starter.IndexOf('.') - 1; } else { list.PreselectionLength = starter.Length; } } editor.ShowCompletionWindow(list); return(true); } else { // DO NOT USE CompletionDataHelper.CreateListForContext here!!! results in endless recursion!!!! if (context.Attribute != null) { if (!DoMarkupExtensionCompletion(context)) { var completionList = new XamlCompletionItemList(context); completionList.PreselectionLength = editor.GetWordBeforeCaretExtended().Length; if ((context.ActiveElement.Name == "Setter" || context.ActiveElement.Name == "EventSetter") && (context.Attribute.Name == "Property" || context.Attribute.Name == "Value")) { DoSetterAndEventSetterCompletion(context, completionList); } else if ((context.ActiveElement.Name.EndsWith("Trigger") || context.ActiveElement.Name == "Condition") && context.Attribute.Name == "Value") { DoTriggerCompletion(context, completionList); } else { if (context.Attribute.Name == "xml:space") { completionList.Items.AddRange(new[] { new SpecialCompletionItem("preserve"), new SpecialCompletionItem("default") }); } var mrr = XamlResolver.Resolve(context.Attribute.Name, context) as MemberResolveResult; if (mrr != null && mrr.ResolvedType != null) { completionList.Items.AddRange(CompletionDataHelper.MemberCompletion(context, mrr.ResolvedType, string.Empty)); editor.ShowInsightWindow(CompletionDataHelper.MemberInsight(mrr)); if (mrr.ResolvedType.FullyQualifiedName == "System.Windows.PropertyPath") { string start = editor.GetWordBeforeCaretExtended(); int index = start.LastIndexOfAny(PropertyPathTokenizer.ControlChars); if (index + 1 < start.Length) { start = start.Substring(index + 1); } else { start = ""; } completionList.PreselectionLength = start.Length; } else if (mrr.ResolvedType.FullyQualifiedName == "System.Windows.Media.FontFamily") { string text = context.ValueStartOffset > -1 ? context.RawAttributeValue.Substring(0, Math.Min(context.ValueStartOffset, context.RawAttributeValue.Length)) : ""; int lastComma = text.LastIndexOf(','); completionList.PreselectionLength = lastComma == -1 ? context.ValueStartOffset : context.ValueStartOffset - lastComma - 1; } } } completionList.SortItems(); if (context.Attribute.Prefix.Equals("xmlns", StringComparison.OrdinalIgnoreCase) || context.Attribute.Name.Equals("xmlns", StringComparison.OrdinalIgnoreCase)) { completionList.Items.AddRange(CompletionDataHelper.CreateListForXmlnsCompletion(context.ProjectContent)); } ICompletionListWindow window = editor.ShowCompletionWindow(completionList); if ((context.Attribute.Prefix.Equals("xmlns", StringComparison.OrdinalIgnoreCase) || context.Attribute.Name.Equals("xmlns", StringComparison.OrdinalIgnoreCase)) && window != null) { window.Width = 400; } return(completionList.Items.Any()); } return(true); } } } return(false); }
void DoStaticTypeCompletion(AttributeValue selItem, XamlCompletionItemList list, XamlCompletionContext context) { var items = GetClassesFromContext(context); foreach (var ns in items) { string key = ns.Key; if (!string.IsNullOrEmpty(key)) key += ":"; list.Items.AddRange( ns.Value .Where(c => c.Fields.Any(f => f.IsStatic) || c.Properties.Any(p => p.IsStatic)) .Select(c => new XamlCompletionItem(key + c.Name, c)) ); } if (selItem != null && selItem.IsString) { list.PreselectionLength = selItem.StringValue.Length; } }
static IReturnType Resolve(this PropertyPathSegment segment, XamlCompletionContext context, IReturnType previousType) { if (segment.Kind == SegmentKind.SourceTraversal) return previousType; if (segment.Kind == SegmentKind.ControlChar) return previousType; string content = segment.Content; if (segment.Kind == SegmentKind.AttachedProperty && content.StartsWith("(")) { content = content.TrimStart('('); if (content.Contains(".")) content = content.Remove(content.IndexOf('.')); } XamlContextDescription tmp = context.Description; context.Description = XamlContextDescription.InTag; ResolveResult rr = XamlResolver.Resolve(content, context); IReturnType type = null; if (rr is TypeResolveResult) type = (rr as TypeResolveResult).ResolvedType; if (previousType != null) { IMember member = previousType.GetMemberByName(content); if (member != null) type = member.ReturnType; } else { if (rr is MemberResolveResult) { MemberResolveResult mrr = rr as MemberResolveResult; if (mrr.ResolvedMember != null) type = mrr.ResolvedMember.ReturnType; } if (rr is TypeResolveResult) type = (rr as TypeResolveResult).ResolvedType; } context.Description = tmp; return type; }
public IEnumerable<ICompletionItem> FindMatchingEventHandlers(XamlCompletionContext context, IEvent member, string targetName) { ITypeDefinition td = member.ReturnType.GetDefinition(); if (td == null) yield break; IMethod delegateInvoker = td.GetMethods(m => m.Name == "Invoke").FirstOrDefault(); if (delegateInvoker == null) yield break; if (context.ParseInformation == null) yield break; var file = context.ParseInformation.UnresolvedFile; var loc = context.Editor.Caret.Location; var unresolved = file.GetInnermostTypeDefinition(loc.Line, loc.Column); if (unresolved == null) yield break; IType type = unresolved.Resolve(new SimpleTypeResolveContext(compilation.MainAssembly)).GetDefinition(); foreach (IMethod method in type.GetMethods(m => m.Parameters.Count == delegateInvoker.Parameters.Count)) { if (!method.ReturnType.Equals(delegateInvoker.ReturnType)) continue; if (method.Parameters.SequenceEqual(delegateInvoker.Parameters, new ParameterComparer())) { yield return new XamlCompletionItem(method); } } yield return new NewEventCompletionItem(member, targetName); }
static void DoSetterAndEventSetterCompletion(XamlCompletionContext context, XamlCompletionItemList completionList) { bool isExplicit; string element = context.ParentElement.Name.EndsWith("Trigger") ? "Trigger" : context.ParentElement.Name; AttributeValue value = MarkupExtensionParser.ParseValue(CompletionDataHelper.LookForTargetTypeValue(context, out isExplicit, element) ?? string.Empty); IReturnType typeName = null; string typeNameString = null; if (!value.IsString) { typeNameString = CompletionDataHelper.GetTypeNameFromTypeExtension(value.ExtensionValue, context); typeName = CompletionDataHelper.ResolveType(typeNameString, context); } else { typeNameString = value.StringValue; typeName = CompletionDataHelper.ResolveType(value.StringValue, context); } if (typeName != null) { switch (context.Attribute.Name) { case "Value": AttributeValue propType = MarkupExtensionParser.ParseValue(context.ActiveElement.GetAttributeValue("Property") ?? ""); if (!propType.IsString) { break; } context.Description = XamlContextDescription.AtTag; string name = propType.StringValue; if (!name.Contains(".")) { name = typeNameString + "." + name; } var member = XamlResolver.Resolve(name, context) 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 XamlCodeCompletionItem(prop)) ); break; case "Event": completionList.Items.AddRange( typeName.GetEvents() .Where(e => e.IsPublic) .Select(evt => new XamlCodeCompletionItem(evt)) ); break; case "Handler": var loc3 = context.Editor.Document.OffsetToPosition(XmlParser.GetActiveElementStartIndex(context.Editor.Document.Text, context.Editor.Caret.Offset)); AttributeValue evtType = MarkupExtensionParser.ParseValue(context.ActiveElement.GetAttributeValue("Event") ?? ""); if (!evtType.IsString) { break; } string evtName = evtType.StringValue; if (!evtName.Contains(".")) { evtName = typeNameString + "." + evtName; } var evtMember = XamlResolver.Resolve(evtName, context) as MemberResolveResult; if (evtMember == null || evtMember.ResolvedMember == null || !(evtMember.ResolvedMember is IEvent) || evtMember.ResolvedMember.ReturnType == null) { break; } IClass c = (evtMember.ResolvedMember as IEvent).ReturnType.GetUnderlyingClass(); if (c == null) { break; } IMethod invoker = c.Methods.FirstOrDefault(m => m.Name == "Invoke"); if (invoker == null) { break; } completionList.Items.AddRange( CompletionDataHelper.AddMatchingEventHandlers(context, invoker).Add(new NewEventCompletionItem(evtMember.ResolvedMember as IEvent, typeName.Name)) ); break; } } }
IList<ICompletionItem> CreatePropertyPathCompletion(XamlCompletionContext context) { bool isExplicit; IType typeName = GetType(context, out isExplicit); IList<ICompletionItem> list = new List<ICompletionItem>(); string value = context.ValueStartOffset > -1 ? context.RawAttributeValue.Substring(0, Math.Min(context.ValueStartOffset + 1, context.RawAttributeValue.Length)) : ""; if (value.EndsWithAny(']', ')')) return list; var segments = PropertyPathParser.Parse(value).ToList(); int completionStart; bool isAtDot = false; IType propertyPathType = ResolvePropertyPath(segments, context, typeName, out completionStart); if (completionStart < segments.Count) { PropertyPathSegment seg = segments[completionStart]; switch (seg.Kind) { case SegmentKind.ControlChar: if (seg.Content == ".") { AddAttributes(propertyPathType, list, false); isAtDot = true; } break; case SegmentKind.AttachedProperty: AddAttributes(seg.Resolve(context, propertyPathType), list, false); isAtDot = seg.Content.Contains("."); break; case SegmentKind.PropertyOrType: AddAttributes(propertyPathType, list, false); isAtDot = true; break; } } else if (typeName != null) { AddAttributes(typeName, list, false); } if (!isAtDot) { foreach (var item in GetAllTypes(context)) list.Add(item); } return list; }
/// <summary> /// Returns the list of allow XAML2009 completion items. /// </summary> public static IEnumerable<string> GetAllowedItems(XamlCompletionContext context) { string xamlPrefix = context.XamlNamespacePrefix; string xKey = string.IsNullOrEmpty(xamlPrefix) ? "" : xamlPrefix + ":"; var compilation = SD.ParserService.GetCompilationForFile(context.Editor.FileName); var resolver = new XamlAstResolver(compilation, context.ParseInformation); // TODO : add support for x:Key as attribute element (XAML 2009 only) switch (context.Description) { case XamlContextDescription.AtTag: if (context.ParentElement != null && string.Equals(context.ParentElement.Name, xKey + "Members", StringComparison.OrdinalIgnoreCase)) { yield return xKey + "Member"; yield return xKey + "Property"; } else if (context.ParentElement == context.RootElement && context.RootElement.Attributes.Any(attr => string.Equals(attr.Name, xKey + "Class", StringComparison.OrdinalIgnoreCase))) { yield return xKey + "Code"; yield return xKey + "Members"; } else { if (context.ParentElement != null && string.Equals(context.ParentElement.Name, xKey + "Code", StringComparison.OrdinalIgnoreCase)) yield break; yield return xKey + "Array"; yield return xKey + "Boolean"; yield return xKey + "Byte"; yield return xKey + "Char"; yield return xKey + "Decimal"; yield return xKey + "Dictionary"; yield return xKey + "Double"; yield return xKey + "Int16"; yield return xKey + "Int32"; yield return xKey + "Int64"; yield return xKey + "List"; yield return xKey + "Object"; yield return xKey + "Reference"; yield return xKey + "Single"; yield return xKey + "String"; yield return xKey + "TimeSpan"; yield return xKey + "Uri"; if (context.RootElement.Attributes.Any(attr => string.Equals(attr.Name, xKey + "Class", StringComparison.OrdinalIgnoreCase))) yield return xKey + "Members"; } break; case XamlContextDescription.InTag: yield return xKey + "Uid"; if (context.InRoot) { yield return xKey + "Class"; yield return xKey + "ClassModifier"; yield return xKey + "Subclass"; yield return xKey + "Name"; } else { var resourceDictionaryType = compilation.FindType(typeof(ResourceDictionary)); if (context.ActiveElement != null && string.Equals(context.ActiveElement.Name, xKey + "Array", StringComparison.OrdinalIgnoreCase)) { yield return "Type"; } else if (context.ActiveElement != null && string.Equals(context.ActiveElement.Name, xKey + "Member", StringComparison.OrdinalIgnoreCase)) { yield return "Name"; } else if (context.ActiveElement != null && string.Equals(context.ActiveElement.Name, xKey + "Property", StringComparison.OrdinalIgnoreCase)) { yield return "Name"; yield return "Type"; } else if (context.RootElement.Attributes.Any(attr => string.Equals(attr.Name, xKey + "Class", StringComparison.OrdinalIgnoreCase))) { yield return xKey + "FieldModifier"; yield return xKey + "Name"; } else { yield return xKey + "Name"; } if (context.ParentElement != null) { var rr = resolver.ResolveElement(context.ParentElement); if (rr != null) { if (rr.Type.Equals(resourceDictionaryType)) { yield return xKey + "Key"; yield return xKey + "Shared"; } else if (rr.Type.TypeParameterCount > 0) { yield return xKey + "TypeArguments"; } } } } break; } yield break; }
static IType ResolvePropertyPath(IList<PropertyPathSegment> segments, XamlCompletionContext context, IType parentType, out int lastIndex) { IType type = parentType; for (lastIndex = 0; lastIndex < segments.Count - 1; lastIndex++) { PropertyPathSegment segment = segments[lastIndex]; switch (segment.Kind) { case SegmentKind.AttachedProperty: // do we need to take account of previous results? type = segment.Resolve(context, null); break; case SegmentKind.ControlChar: if (segment.Content == "[" || segment.Content == "(" || segment.Content == "/") return null; return type; case SegmentKind.PropertyOrType: type = segment.Resolve(context, type); break; case SegmentKind.Indexer: if (type != null) { IProperty prop = type.GetProperties(p => p.IsIndexer).FirstOrDefault(); if (prop != null) { type = prop.ReturnType; } } break; case SegmentKind.SourceTraversal: // ignore return null; } } return type; }
public IList<ICompletionItem> CreateElementList(XamlCompletionContext context, bool includeAbstract) { if (context.ParseInformation == null) return EmptyList<ICompletionItem>.Instance; List<ICompletionItem> result = new List<ICompletionItem>(); AXmlElement last = context.ParentElement; ITextEditor editor = context.Editor; compilation = SD.ParserService.GetCompilationForFile(editor.FileName); IUnresolvedFile file = context.ParseInformation.UnresolvedFile; foreach (string item in XamlConst.GetAllowedItems(context)) { result.Add(new XamlCompletionItem(item)); } IType rt = null; if (last != null) { if (string.Equals(last.Prefix, context.XamlNamespacePrefix, StringComparison.OrdinalIgnoreCase)) { if (string.Equals(last.LocalName, "Members", StringComparison.OrdinalIgnoreCase)) return result; if (string.Equals(last.LocalName, "Code", StringComparison.OrdinalIgnoreCase)) return result; } // If we have an element that is not a property or an incomplete // definition => interpret element as a type. XamlResolver resolver = new XamlResolver(compilation); int dotIndex = last.LocalName.IndexOf(".", StringComparison.Ordinal) + 1; if (dotIndex < 1 || dotIndex == last.LocalName.Length) { rt = resolver.ResolveType(last.Namespace, last.LocalName.Trim('.')); string contentPropertyName = GetContentPropertyName(rt.GetDefinition()); // If the type has a content property specified, use its type for completion. if (!string.IsNullOrEmpty(contentPropertyName)) { IProperty p = rt.GetProperties(m => m.Name == contentPropertyName).FirstOrDefault(); if (p != null) { rt = p.ReturnType; } } } else { string typeName = last.LocalName.Substring(0, dotIndex - 1); string memberName = last.LocalName.Substring(dotIndex); rt = resolver.ResolveType(last.Namespace, typeName); IMember member = rt.GetMembers(m => m.Name == memberName).FirstOrDefault(); if (member != null) { rt = member.ReturnType; } } } bool parentAdded = false; var utd = file.GetInnermostTypeDefinition(editor.Caret.Location); ITypeDefinition currentTypeDef = null; if (utd != null) { currentTypeDef = utd.Resolve(new SimpleTypeResolveContext(compilation.MainAssembly)).GetDefinition(); } MemberLookup memberLookup = new MemberLookup(currentTypeDef, compilation.MainAssembly); IList<ITypeDefinition> possibleTypesInCollection = EmptyList<ITypeDefinition>.Instance; if (rt != null && Extensions.IsListType(rt)) { possibleTypesInCollection = rt.GetMethods(m => m.Parameters.Count == 1 && "Add".Equals(m.Name, StringComparison.Ordinal)) .Select(m => m.Parameters[0].Type.GetDefinition()) .Where(t => t != null) .ToList(); } var items = GetClassesFromContext(context); foreach (var ns in items) { foreach (ITypeDefinition td in ns.Value) { if (td.Kind != TypeKind.Class && (!includeAbstract || td.Kind != TypeKind.Interface)) continue; if (td.IsStatic || (!includeAbstract && td.IsAbstract) || td.IsDerivedFrom(KnownTypeCode.Attribute)) continue; if (td.Kind == TypeKind.Class && !td.GetConstructors().Any(m => memberLookup.IsAccessible(m, false))) continue; if (possibleTypesInCollection.Count > 0 && !possibleTypesInCollection.Any(td.IsDerivedFrom)) continue; string fullName = td.Name; if (!string.IsNullOrEmpty(ns.Key)) fullName = ns.Key + ":" + fullName; XamlCompletionItem item = new XamlCompletionItem(fullName, td); parentAdded = parentAdded || (last != null && item.Text == last.Name); result.Add(item); } } // TODO reimplement this if it is really necessary. // if (!parentAdded && last != null && !last.Name.Contains(".")) { // IClass itemClass = cu.CreateType(last.Namespace, last.LocalName.Trim('.')).GetUnderlyingClass(); // if (itemClass != null) // result.Add(new XamlCodeCompletionItem(itemClass, last.Prefix)); // } return result; }
static bool CreateEventHandlerCode(XamlCompletionContext context, NewEventCompletionItem completionItem) { IProject project = SD.ProjectService.FindProjectContainingFile(context.Editor.FileName); if (project == null) return false; var unresolved = context.ParseInformation.UnresolvedFile.TypeDefinition; if (unresolved == null) return false; var compilation = SD.ParserService.GetCompilationForFile(context.Editor.FileName); var definition = unresolved.Resolve(new SimpleTypeResolveContext(compilation.MainAssembly)).GetDefinition(); project.LanguageBinding.CodeGenerator.InsertEventHandler(definition, completionItem.HandlerName, completionItem.EventType, true); return true; }
IList<ICompletionItem> CreateAttributeList(XamlCompletionContext context, bool includeEvents) { if (context.ParseInformation == null) return EmptyList<ICompletionItem>.Instance; AXmlElement lastElement = context.ActiveElement; IUnresolvedFile file = context.ParseInformation.UnresolvedFile; XamlResolver resolver = new XamlResolver(compilation); IType type = resolver.ResolveType(lastElement.Namespace, lastElement.LocalName.Trim('.')); var list = new List<ICompletionItem>(); string xamlPrefix = context.XamlNamespacePrefix; string xKey = string.IsNullOrEmpty(xamlPrefix) ? "" : xamlPrefix + ":"; if (context.Description == XamlContextDescription.InTag) list.AddRange(XamlConst.GetAllowedItems(context).Select(item => new XamlCompletionItem(item))); if (string.Equals(lastElement.Prefix, context.XamlNamespacePrefix, StringComparison.OrdinalIgnoreCase) && XamlConst.IsBuiltin(lastElement.LocalName)) return list; if (lastElement.LocalName.EndsWith(".", StringComparison.OrdinalIgnoreCase) || context.PressedKey == '.') { if (type.Kind == TypeKind.Unknown) return EmptyList<ICompletionItem>.Instance; if (context.ParentElement != null && context.ParentElement.LocalName.StartsWith(lastElement.LocalName.TrimEnd('.'), StringComparison.OrdinalIgnoreCase)) { AddAttributes(type, list, includeEvents); } AddAttachedProperties(type.GetDefinition(), list); } else { if (type.Kind != TypeKind.Unknown) { AddAttributes(type, list, includeEvents); list.AddRange(GetListOfAttached(context, null, includeEvents, true)); } } return list; }
void DoTriggerCompletion(XamlCompletionContext context, XamlCompletionItemList completionList) { bool isExplicit; AttributeValue value = MarkupExtensionParser.ParseValue(Utils.LookForTargetTypeValue(context, out isExplicit, "Trigger") ?? string.Empty); string typeNameString; var rr = resolver.ResolveAttributeValue(context, value, out typeNameString); var typeName = rr.Type; if (typeName != null) { switch (context.Attribute.Name) { case "Value": AttributeValue propType = MarkupExtensionParser.ParseValue(context.ActiveElement.GetAttributeValue("Property") ?? ""); if (!propType.IsString) break; string name = propType.StringValue; if (!name.Contains(".")) name = typeNameString + "." + name; context.Description = XamlContextDescription.AtTag; var mrr = resolver.ResolveExpression(name, context) as MemberResolveResult; if (mrr == null || mrr.Member == null) break; completionList.Items.AddRange( generator.MemberCompletion(context, mrr.Member.ReturnType, string.Empty) ); break; } } }
public IEnumerable<ICompletionItem> MemberCompletion(XamlCompletionContext context, IType type, string textPrefix = "") { ITextEditor editor = context.Editor; compilation = SD.ParserService.GetCompilationForFile(editor.FileName); string xamlPrefix = context.XamlNamespacePrefix; string xKey = string.IsNullOrEmpty(xamlPrefix) ? "" : xamlPrefix + ":"; if (type.Name == typeof(System.Nullable<>).Name) { yield return new XamlCompletionItem("{" + xKey + "Null}"); type = type.TypeArguments.FirstOrDefault(); if (type == null) yield break; } ITypeDefinition definition = type.GetDefinition(); if (definition == null) yield break; definition.IsCollectionType(); switch (definition.KnownTypeCode) { case KnownTypeCode.Array: case KnownTypeCode.ICollection: case KnownTypeCode.ICollectionOfT: case KnownTypeCode.IEnumerable: case KnownTypeCode.IEnumerableOfT: yield return new XamlCompletionItem("{" + xKey + "Array}"); break; } switch (definition.Kind) { case TypeKind.Class: IType typeName; bool isExplicit, showFull = false; switch (definition.FullName) { case "System.String": // return nothing break; case "System.Type": foreach (var item in CreateElementList(context, true)) yield return item; break; case "System.Windows.PropertyPath": foreach (var item in CreatePropertyPathCompletion(context)) yield return item; break; case "System.Windows.DependencyProperty": typeName = GetType(context, out isExplicit); bool isReadOnly = context.ActiveElement.Name.EndsWith("Trigger", StringComparison.Ordinal); if (!isExplicit && ((context.ValueStartOffset > 0) ? context.RawAttributeValue.Substring(0, context.ValueStartOffset) : "").Contains(".")) showFull = true; if (typeName != null) { foreach (var item in typeName.GetDependencyProperties(true, !isExplicit, !isReadOnly, showFull)) yield return item; } break; case "System.Windows.RoutedEvent": typeName = GetType(context, out isExplicit); if (!isExplicit && ((context.ValueStartOffset > 0) ? context.RawAttributeValue.Substring(0, context.ValueStartOffset) : "").Contains(".")) showFull = true; if (typeName != null) { foreach (var item in typeName.GetRoutedEvents(true, !isExplicit, showFull)) yield return item; } break; case "System.Windows.Media.FontFamily": foreach (var font in Fonts.SystemFontFamilies) yield return new XamlCompletionItem(font.FamilyNames.First().Value) { Image = ClassBrowserIconService.Const }; break; default: if (context.Description == XamlContextDescription.InMarkupExtension) { foreach (IField f in definition.Fields) yield return new XamlCompletionItem(textPrefix + f.Name, f); foreach (IProperty p in definition.GetProperties(pr => pr.IsPublic && pr.IsStatic && pr.CanGet)) yield return new XamlCompletionItem(textPrefix + p.Name, p); } break; } break; case TypeKind.Enum: foreach (IField f in definition.Fields) yield return new XamlCompletionItem(textPrefix + f.Name, f); foreach (IProperty p in definition.Properties.Where(pr => pr.IsPublic && pr.IsStatic && pr.CanGet)) yield return new XamlCompletionItem(textPrefix + p.Name, p); break; case TypeKind.Struct: switch (definition.FullName) { case "System.Boolean": yield return new DefaultCompletionItem("True") { Image = ClassBrowserIconService.Const }; yield return new DefaultCompletionItem("False") { Image = ClassBrowserIconService.Const }; break; case "System.Windows.GridLength": yield return new XamlCompletionItem("Auto") { Image = ClassBrowserIconService.Const }; yield return new XamlCompletionItem("*") { Image = ClassBrowserIconService.Const }; break; } break; case TypeKind.Delegate: foreach (var item in CreateEventCompletion(context, definition)) yield return item; break; } var classes = definition.ParentAssembly .GetAllTypeDefinitions() .Where(cla => cla.FullName == definition.FullName + "s" || cla.FullName == definition.FullName + "es"); foreach (var coll in classes) { foreach (var item in coll.Properties) yield return new XamlCompletionItem(item); foreach (var item in coll.Fields.Where(f => f.IsPublic && f.IsStatic && f.ReturnType.FullName == definition.FullName)) yield return new XamlCompletionItem(item); } }
bool DoAttributeCompletion(XamlCompletionContext context, XamlCompletionItemList completionList) { XamlAstResolver resolver = new XamlAstResolver(compilation, context.ParseInformation); ITextEditor editor = context.Editor; var mrr = resolver.ResolveAttribute(context.Attribute) as MemberResolveResult; if (mrr != null && mrr.Type.Kind != TypeKind.Unknown) { completionList.Items.AddRange(generator.MemberCompletion(context, mrr.Type, string.Empty)); editor.ShowInsightWindow(generator.MemberInsight(mrr)); editor.ShowCompletionWindow(completionList); switch (mrr.Type.FullName) { case "System.Windows.PropertyPath": string start = editor.GetWordBeforeCaretExtended(); int index = start.LastIndexOfAny(PropertyPathTokenizer.ControlChars); if (index + 1 < start.Length) { start = start.Substring(index + 1); } else { start = ""; } completionList.PreselectionLength = start.Length; break; case "System.Windows.Media.FontFamily": string text = context.ValueStartOffset > -1 ? context.RawAttributeValue.Substring(0, Math.Min(context.ValueStartOffset, context.RawAttributeValue.Length)) : ""; int lastComma = text.LastIndexOf(','); completionList.PreselectionLength = lastComma == -1 ? context.ValueStartOffset : context.ValueStartOffset - lastComma - 1; break; } } return completionList.Items.Any(); }
public IEnumerable<IInsightItem> CreateMarkupExtensionInsight(XamlCompletionContext context) { var markup = Utils.GetMarkupExtensionAtPosition(context.AttributeValue.ExtensionValue, context.ValueStartOffset); var resolver = new XamlResolver(compilation); var type = (resolver.ResolveExpression(markup.ExtensionType, context) ?? resolver.ResolveExpression(markup.ExtensionType + "Extension", context)).Type; if (type != null) { var ctors = type .GetMethods(m => m.IsPublic && m.IsConstructor && m.Parameters.Count >= markup.PositionalArguments.Count) .OrderBy(m => m.Parameters.Count); foreach (var ctor in ctors) yield return new MarkupExtensionInsightItem(ctor); } }
bool DoMarkupExtensionCompletion(XamlCompletionContext context) { if (context.Description == XamlContextDescription.InMarkupExtension && context.AttributeValue != null && !context.AttributeValue.IsString) { if (!XamlBindingOptions.UseExtensionCompletion) return false; XamlCompletionItemList completionList = generator.CreateMarkupExtensionCompletion(context) as XamlCompletionItemList; string word = context.Editor.GetWordBeforeCaretExtended(); if (context.PressedKey != '.' && context.PressedKey != '=' && !word.EndsWith(".", StringComparison.Ordinal) && completionList.PreselectionLength == 0) completionList.PreselectionLength = word.Length; var insightList = generator.CreateMarkupExtensionInsight(context); context.Editor.ShowInsightWindow(insightList); context.Editor.ShowCompletionWindow(completionList); return completionList.Items.Any() || insightList.Any(); } return false; }
public override void Complete(CompletionContext context, ICompletionItem item) { using (context.Editor.Document.OpenUndoGroup()) { base.Complete(context, item); XamlCompletionContext xamlContext = XamlContextResolver.ResolveCompletionContext(context.Editor, context.CompletionChar); if (xamlContext.Description == XamlContextDescription.None && (context.StartOffset <= 0 || context.Editor.Document.GetCharAt(context.StartOffset - 1) != '<')) { context.Editor.Document.Insert(context.StartOffset, "<"); context.EndOffset++; } if (item is XamlCompletionItem && !item.Text.EndsWith(":", StringComparison.Ordinal)) { XamlCompletionItem cItem = item as XamlCompletionItem; if (xamlContext.Description == XamlContextDescription.InTag) { context.Editor.Document.Insert(context.EndOffset, "=\"\""); context.CompletionCharHandled = context.CompletionChar == '='; context.Editor.Caret.Offset--; new XamlCodeCompletionBinding().CtrlSpace(context.Editor); } else if (xamlContext.Description == XamlContextDescription.InMarkupExtension && !string.IsNullOrEmpty(xamlContext.RawAttributeValue)) { string valuePart = xamlContext.RawAttributeValue.Substring(0, xamlContext.ValueStartOffset); AttributeValue value = MarkupExtensionParser.ParseValue(valuePart); if (value != null && !value.IsString) { 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().TrimEnd(); int spaces = CountWhiteSpacesAtEnd(context.Editor.GetWordBeforeCaret()); int typeNameStart = markup.ExtensionType.IndexOf(':') + 1; if (!(word == "." || word == "," || word == ":") && 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; } } if (cItem.Text.EndsWith("=", StringComparison.OrdinalIgnoreCase)) { new XamlCodeCompletionBinding().CtrlSpace(context.Editor); } } } if (item is NewEventCompletionItem) { CreateEventHandlerCode(xamlContext, item as NewEventCompletionItem); } if (item is XmlnsCompletionItem) { context.Editor.Caret.Offset++; } switch (item.Text) { case "![CDATA[": context.Editor.Document.Insert(context.Editor.Caret.Offset, "]]>"); context.Editor.Caret.Offset -= 3; break; case "?": context.Editor.Document.Insert(context.Editor.Caret.Offset, "?>"); context.Editor.Caret.Offset -= 2; break; case "!--": context.Editor.Document.Insert(context.Editor.Caret.Offset, " -->"); context.Editor.Caret.Offset -= 4; break; } if (item.Text.StartsWith("/", StringComparison.OrdinalIgnoreCase)) { context.Editor.Document.Insert(context.EndOffset, ">"); context.CompletionCharHandled = context.CompletionChar == '>'; context.Editor.Caret.Offset++; } } }