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 override void Complete(CompletionContext context, ICompletionItem item)
        {
            using (context.Editor.Document.OpenUndoGroup()) {
                base.Complete(context, item);

                XamlCompletionContext xamlContext = XamlContextResolver.ResolveCompletionContext(context.Editor, context.CompletionChar);

                if (xamlContext.Description == XamlContextDescription.None && (context.StartOffset <= 0 || context.Editor.Document.GetCharAt(context.StartOffset - 1) != '<'))
                {
                    context.Editor.Document.Insert(context.StartOffset, "<");
                    context.EndOffset++;
                }

                if (item is XamlCompletionItem && !item.Text.EndsWith(":", StringComparison.Ordinal))
                {
                    XamlCompletionItem cItem = item as XamlCompletionItem;

                    if (xamlContext.Description == XamlContextDescription.InTag)
                    {
                        context.Editor.Document.Insert(context.EndOffset, "=\"\"");
                        context.CompletionCharHandled = context.CompletionChar == '=';
                        context.Editor.Caret.Offset--;
                        new XamlCodeCompletionBinding().CtrlSpace(context.Editor);
                    }
                    else if (xamlContext.Description == XamlContextDescription.InMarkupExtension && !string.IsNullOrEmpty(xamlContext.RawAttributeValue))
                    {
                        string         valuePart = xamlContext.RawAttributeValue.Substring(0, xamlContext.ValueStartOffset);
                        AttributeValue value     = MarkupExtensionParser.ParseValue(valuePart);

                        if (value != null && !value.IsString)
                        {
                            var markup = Utils.GetMarkupExtensionAtPosition(value.ExtensionValue, context.Editor.Caret.Offset);
                            if (markup.NamedArguments.Count > 0 || markup.PositionalArguments.Count > 0)
                            {
                                int oldOffset = context.Editor.Caret.Offset;
                                context.Editor.Caret.Offset = context.StartOffset;
                                string word          = context.Editor.GetWordBeforeCaret().TrimEnd();
                                int    spaces        = CountWhiteSpacesAtEnd(context.Editor.GetWordBeforeCaret());
                                int    typeNameStart = markup.ExtensionType.IndexOf(':') + 1;

                                if (!(word == "." || word == "," || word == ":") && markup.ExtensionType.Substring(typeNameStart, markup.ExtensionType.Length - typeNameStart) != word)
                                {
                                    context.Editor.Document.Replace(context.Editor.Caret.Offset - spaces, spaces, ", ");
                                    oldOffset += (2 - spaces);
                                }

                                context.Editor.Caret.Offset = oldOffset;
                            }
                        }

                        if (cItem.Text.EndsWith("=", StringComparison.OrdinalIgnoreCase))
                        {
                            new XamlCodeCompletionBinding().CtrlSpace(context.Editor);
                        }
                    }
                }

                if (item is NewEventCompletionItem)
                {
                    CreateEventHandlerCode(xamlContext, item as NewEventCompletionItem);
                }

                if (item is XmlnsCompletionItem)
                {
                    context.Editor.Caret.Offset++;
                }

                switch (item.Text)
                {
                case "![CDATA[":
                    context.Editor.Document.Insert(context.Editor.Caret.Offset, "]]>");
                    context.Editor.Caret.Offset -= 3;
                    break;

                case "?":
                    context.Editor.Document.Insert(context.Editor.Caret.Offset, "?>");
                    context.Editor.Caret.Offset -= 2;
                    break;

                case "!--":
                    context.Editor.Document.Insert(context.Editor.Caret.Offset, "  -->");
                    context.Editor.Caret.Offset -= 4;
                    break;
                }

                if (item.Text.StartsWith("/", StringComparison.OrdinalIgnoreCase))
                {
                    context.Editor.Document.Insert(context.EndOffset, ">");
                    context.CompletionCharHandled = context.CompletionChar == '>';
                    context.Editor.Caret.Offset++;
                }
            }
        }
        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);
        }