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); }