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;
                }
            }
        }
示例#3
0
        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);
        }
示例#4
0
        /// <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);
        }
示例#5
0
        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 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 DoMarkupExtensionCompletion(XamlCompletionContext context)
        {
            if (context.Description == XamlContextDescription.InMarkupExtension && context.AttributeValue != null && !context.AttributeValue.IsString)
            {
                if (!XamlBindingOptions.UseExtensionCompletion)
                {
                    return(false);
                }
                XamlCompletionItemList completionList = CompletionDataHelper.CreateMarkupExtensionCompletion(context) as XamlCompletionItemList;
                string word = context.Editor.GetWordBeforeCaretExtended();
                if (context.PressedKey != '.' && context.PressedKey != '=' && !word.EndsWith(".") && completionList.PreselectionLength == 0)
                {
                    completionList.PreselectionLength = word.Length;
                }
                var insightList = CompletionDataHelper.CreateMarkupExtensionInsight(context);
                context.Editor.ShowInsightWindow(insightList);
                context.Editor.ShowCompletionWindow(completionList);
                return(completionList.Items.Any() || insightList.Any());
            }

            return(false);
        }
        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;
                }
            }
        }
示例#9
0
        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;
            }
        }
示例#10
0
        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 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;
		}
		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)));
		}
		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 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 static XamlCompletionItemList CreateListForContext(XamlCompletionContext context)
		{
			XamlCompletionItemList list = new XamlCompletionItemList(context);
			
			ParseInformation info = context.ParseInformation;
			ITextEditor editor = context.Editor;
			
			switch (context.Description) {
				case XamlContextDescription.None:
					if (context.Forced) {
						list.Items.AddRange(standardElements);
						list.Items.AddRange(CreateElementList(context, false, false));
						AddClosingTagCompletion(context, list);
					}
					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, false));
						AddClosingTagCompletion(context, list);
					}
					break;
				case XamlContextDescription.InTag:
					DebugTimer.Start();
					
					string word = context.Editor.GetWordBeforeCaretExtended();
					
					if (context.PressedKey == '.' || word.Contains(".")) {
						string ns = "";
						int pos = word.IndexOf(':');
						if (pos > -1)
							ns = word.Substring(0, pos);
						
						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('.');
						}
						TypeResolveResult trr = XamlResolver.Resolve(className, context) as TypeResolveResult;
						IClass typeClass = (trr != null && trr.ResolvedType != null) ? trr.ResolvedType.GetUnderlyingClass() : null;
						
						if (typeClass != null && typeClass.HasAttached(true, true))
							list.Items.AddRange(GetListOfAttached(context, element, ns, true, true));
					} else {
						QualifiedNameWithLocation last = context.ActiveElement.ToQualifiedName();
						TypeResolveResult trr = XamlResolver.Resolve(last.Name, context) as TypeResolveResult;
						IClass typeClass = (trr != null && trr.ResolvedType != null) ? trr.ResolvedType.GetUnderlyingClass() : null;
						list.Items.AddRange(CreateAttributeList(context, true));
						list.Items.AddRange(standardAttributes);
					}
					
					DebugTimer.Stop("CreateListForContext - InTag");
					break;
				case XamlContextDescription.InAttributeValue:
					new XamlCodeCompletionBinding().CtrlSpace(editor);
					break;
			}
			
			list.SortItems();
			
			return list;
		}
        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);
        }
		static void AddClosingTagCompletion(XamlCompletionContext context, XamlCompletionItemList list)
		{
			if (context.ParentElement != null && !context.InRoot) {
				ResolveResult rr = XamlResolver.Resolve(context.ParentElement.Name, context);
				TypeResolveResult trr = rr as TypeResolveResult;
				MemberResolveResult mrr = rr as MemberResolveResult;

				if (trr != null) {
					if (trr.ResolvedClass == null)
						return;
					list.Items.Add(new XamlCodeCompletionItem("/" + context.ParentElement.Name, trr.ResolvedClass));
				} else if (mrr != null) {
					if (mrr.ResolvedMember == null)
						return;
					list.Items.Add(new XamlCodeCompletionItem("/" + context.ParentElement.Name, mrr.ResolvedMember));
				}
			}
		}
		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;
				}
			}
		}
		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;
			}
		}
		/// <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;
		}
示例#23
0
        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);
        }
		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;
				}
			}
		}
		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 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 + 1, context.RawAttributeValue.Length)) : "";
										int lastComma = text.LastIndexOf(',');
										completionList.PreselectionLength = lastComma == -1 ? context.ValueStartOffset + 1 : context.ValueStartOffset - lastComma;
									}
								}
							}
							
							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;
		}
		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;
		}
		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();
		}
		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;
		}
		void DoSetterAndEventSetterCompletion(XamlCompletionContext context, XamlCompletionItemList completionList)
		{
			string typeNameString;
			int dotIndex;
			IType typeName = ResolveTargetType(context, out typeNameString, out dotIndex,
			                                   string.Equals(context.Attribute.Name, "Property")
			                                   || string.Equals(context.Attribute.Name, "Event"));

			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))
					);
					if (dotIndex == -1) {
						completionList.Items.AddRange(
							generator.GetTypesForPropEventNameCompletion(context, true)
						);
					}
					break;
				case "Event":
					completionList.Items.AddRange(
						typeName.GetEvents()
						.Where(e => e.IsPublic)
						.Select(evt => new XamlCompletionItem(evt))
					);
					if (dotIndex == -1) {
						completionList.Items.AddRange(
							generator.GetTypesForPropEventNameCompletion(context, true)
						);
					}
					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;
			}
		}
		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;
			}
		}
		public static ICompletionItemList CreateMarkupExtensionCompletion(XamlCompletionContext context)
		{
			var list = new XamlCompletionItemList(context);
			string visibleValue = context.RawAttributeValue.Substring(0, Utils.MinMax(context.ValueStartOffset, 0, context.RawAttributeValue.Length));
			if (context.PressedKey == '=')
				visibleValue += "=";
//			context.RawAttributeValue = visibleValue;
//			context.AttributeValue = MarkupExtensionParser.ParseValue(visibleValue);
			var markup = Utils.GetMarkupExtensionAtPosition(context.AttributeValue.ExtensionValue, context.ValueStartOffset);
			var type = ResolveType(markup.ExtensionType, context) ?? ResolveType(markup.ExtensionType + "Extension", context);
			
			if (type == null) {
				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 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 DoSetterAndEventSetterCompletion(XamlCompletionContext context, XamlCompletionItemList completionList)
        {
            string typeNameString;
            int    dotIndex;
            IType  typeName = ResolveTargetType(context, out typeNameString, out dotIndex,
                                                string.Equals(context.Attribute.Name, "Property") ||
                                                string.Equals(context.Attribute.Name, "Event"));

            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))
                    );
                if (dotIndex == -1)
                {
                    completionList.Items.AddRange(
                        generator.GetTypesForPropEventNameCompletion(context, true)
                        );
                }
                break;

            case "Event":
                completionList.Items.AddRange(
                    typeName.GetEvents()
                    .Where(e => e.IsPublic)
                    .Select(evt => new XamlCompletionItem(evt))
                    );
                if (dotIndex == -1)
                {
                    completionList.Items.AddRange(
                        generator.GetTypesForPropEventNameCompletion(context, true)
                        );
                }
                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;
            }
        }