IType GetType(XamlContext context, out bool isExplicit) { string targetTypeValue = Utils.LookForTargetTypeValue(context, out isExplicit, "Trigger", "Setter"); AttributeValue value = MarkupExtensionParser.ParseValue(targetTypeValue ?? string.Empty); XamlResolver resolver = new XamlResolver(compilation); return(resolver.ResolveAttributeValue(context, value).Type); }
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); }
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; } } }
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 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 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)); } } }
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 Process() { try { List <Highlight> results = new List <Highlight>(); foreach (HighlightingInfo info in GetInfo()) { IMember member = null; // Commented out because task doesn't come with cancellation support in .NET 4.0 Beta 2 // (use CancellationToken instead) // I didn't have to remove any call to task.Cancel(), so apparently this was dead code. //if (task.IsCancellationRequested) { // task.AcknowledgeCancellation(); // return; //} // TODO: implement cancellation support if (!info.Token.StartsWith("xmlns", StringComparison.OrdinalIgnoreCase)) { MemberResolveResult rr = XamlResolver.Resolve(info.Token, info.Context) as MemberResolveResult; member = (rr != null) ? rr.ResolvedMember : null; } results.Add(new Highlight() { Member = member, Info = info }); } lock (this) this.results = results; WorkbenchSingleton.SafeThreadAsyncCall(InvokeRedraw); } catch (Exception e) { WorkbenchSingleton.SafeThreadAsyncCall(() => MessageService.ShowException(e)); } }
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))); }
IType GetType(XamlContext context, out bool isExplicit) { string targetTypeValue = Utils.LookForTargetTypeValue(context, out isExplicit, "Trigger", "Setter"); AttributeValue value = MarkupExtensionParser.ParseValue(targetTypeValue ?? string.Empty); XamlResolver resolver = new XamlResolver(compilation); return resolver.ResolveAttributeValue(context, value).Type; }
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 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 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 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); } }
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 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 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 CodeCompletionKeyPressResult HandleKeyPress(ITextEditor editor, char ch) { compilation = SD.ParserService.GetCompilationForFile(editor.FileName); resolver = new XamlResolver(compilation); XamlCompletionContext context = XamlContextResolver.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 = generator.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--; 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) { list = generator.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--; 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 = generator.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++; } 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); } string attributeName = (context.Attribute != null) ? context.Attribute.Name : string.Empty; if (!attributeName.StartsWith("xmlns", StringComparison.OrdinalIgnoreCase)) { return(CtrlSpace(editor, context) ? CodeCompletionKeyPressResult.CompletedIncludeKeyInCompletion : CodeCompletionKeyPressResult.None); } return(CodeCompletionKeyPressResult.None); } break; } return(CodeCompletionKeyPressResult.None); }
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); }
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); }
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); }
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); }
public CodeCompletionKeyPressResult HandleKeyPress(ITextEditor editor, char ch) { compilation = SD.ParserService.GetCompilationForFile(editor.FileName); resolver = new XamlResolver(compilation); XamlCompletionContext context = XamlContextResolver.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 = generator.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--; 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) { list = generator.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--; 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 = generator.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++; } 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; string attributeName = (context.Attribute != null) ? context.Attribute.Name : string.Empty; if (!attributeName.StartsWith("xmlns", StringComparison.OrdinalIgnoreCase)) { return CtrlSpace(editor, context) ? CodeCompletionKeyPressResult.CompletedIncludeKeyInCompletion : CodeCompletionKeyPressResult.None; } return CodeCompletionKeyPressResult.None; } break; } return CodeCompletionKeyPressResult.None; }
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; }