void FormatLineInternal(ITextEditor editor, int lineNr, int cursorOffset, char ch)
        {
            string terminator = DocumentUtilitites.GetLineTerminator(editor.Document, lineNr);

            doCasing    = PropertyService.Get("VBBinding.TextEditor.EnableCasing", true);
            doInsertion = PropertyService.Get("VBBinding.TextEditor.EnableEndConstructs", true);

            IDocumentLine currentLine = editor.Document.GetLine(lineNr);
            IDocumentLine lineAbove   = lineNr > 1 ? editor.Document.GetLine(lineNr - 1) : null;

            string curLineText   = currentLine == null ? "" : currentLine.Text;
            string lineAboveText = lineAbove == null ? "" : lineAbove.Text;

            if (ch == '\'')
            {
                InsertDocumentationComments(editor, lineNr, cursorOffset);
            }

            if (ch == '\n' && lineAboveText != null)
            {
                if (LanguageUtils.IsInsideDocumentationComment(editor, lineAbove, lineAbove.EndOffset))
                {
                    editor.Document.Insert(cursorOffset, "''' ");
                    return;
                }

                string textToReplace = lineAboveText.TrimLine();

                if (doCasing)
                {
                    DoCasingOnLine(lineAbove, textToReplace, editor);
                }

                if (doInsertion)
                {
                    DoInsertionOnLine(terminator, currentLine, lineAbove, textToReplace, editor, lineNr);
                }

                if (IsInString(lineAboveText))
                {
                    if (IsFinishedString(curLineText))
                    {
                        editor.Document.Insert(lineAbove.EndOffset, "\" & _");
                        editor.Document.Insert(currentLine.Offset, "\"");
                    }
                    else
                    {
                        editor.Document.Insert(lineAbove.EndOffset, "\"");
                    }
                }
                else
                {
                    string indent = DocumentUtilitites.GetWhitespaceAfter(editor.Document, lineAbove.Offset);
                    if (indent.Length > 0)
                    {
                        string newLineText = indent + currentLine.Text.Trim();
                        editor.Document.Replace(currentLine.Offset, currentLine.Length, newLineText);
                    }
                    editor.Caret.Column = indent.Length + 1;
                }

                IndentLines(editor, lineNr - 1, lineNr);
            }
            else if (ch == '>')
            {
                if (LanguageUtils.IsInsideDocumentationComment(editor, currentLine, cursorOffset))
                {
                    int column = editor.Caret.Offset - currentLine.Offset;
                    int index  = Math.Min(column - 1, curLineText.Length - 1);

                    while (index > 0 && curLineText[index] != '<')
                    {
                        --index;
                        if (curLineText[index] == '/')
                        {
                            return;                             // the tag was an end tag or already
                        }
                    }

                    if (index > 0)
                    {
                        StringBuilder commentBuilder = new StringBuilder("");
                        for (int i = index; i < curLineText.Length && i < column && !Char.IsWhiteSpace(curLineText[i]); ++i)
                        {
                            commentBuilder.Append(curLineText[i]);
                        }
                        string tag = commentBuilder.ToString().Trim();
                        if (!tag.EndsWith(">", StringComparison.OrdinalIgnoreCase))
                        {
                            tag += ">";
                        }
                        if (!tag.StartsWith("/", StringComparison.OrdinalIgnoreCase))
                        {
                            string endTag = "</" + tag.Substring(1);
                            editor.Document.Insert(editor.Caret.Offset, endTag);
                            editor.Caret.Offset -= endTag.Length;
                        }
                    }
                }
            }
        }
Пример #2
0
        public CodeCompletionKeyPressResult HandleKeyPress(ITextEditor editor, char ch)
        {
            if (LanguageUtils.IsInsideDocumentationComment(editor) && ch == '<')
            {
                new CommentCompletionItemProvider().ShowCompletion(editor);
                return(CodeCompletionKeyPressResult.Completed);
            }

            if (IsInComment(editor) || IsInString(editor))
            {
                return(CodeCompletionKeyPressResult.None);
            }

            if (editor.SelectionLength > 0)
            {
                // allow code completion when overwriting an identifier
                int endOffset = editor.SelectionStart + editor.SelectionLength;
                // but block code completion when overwriting only part of an identifier
                if (endOffset < editor.Document.TextLength && char.IsLetterOrDigit(editor.Document.GetCharAt(endOffset)))
                {
                    return(CodeCompletionKeyPressResult.None);
                }

                editor.Document.Remove(editor.SelectionStart, editor.SelectionLength);
            }

            VBNetExpressionFinder ef = new VBNetExpressionFinder(ParserService.GetParseInformation(editor.FileName));

            ExpressionResult result;

            switch (ch)
            {
            case '(':
                if (CodeCompletionOptions.InsightEnabled)
                {
                    IInsightWindow insightWindow = editor.ShowInsightWindow(new MethodInsightProvider().ProvideInsight(editor));
                    if (insightWindow != null)
                    {
                        insightHandler.InitializeOpenedInsightWindow(editor, insightWindow);
                        insightHandler.HighlightParameter(insightWindow, 0);
                    }
                    return(CodeCompletionKeyPressResult.Completed);
                }
                break;

            case ',':
                if (CodeCompletionOptions.InsightRefreshOnComma && CodeCompletionOptions.InsightEnabled)
                {
                    IInsightWindow insightWindow;
                    if (insightHandler.InsightRefreshOnComma(editor, ch, out insightWindow))
                    {
                        return(CodeCompletionKeyPressResult.Completed);
                    }
                }
                break;

            case '\n':
                TryDeclarationTypeInference(editor, editor.Document.GetLineForOffset(editor.Caret.Offset));
                break;

            case '.':
                string w = editor.GetWordBeforeCaret(); int index = w.IndexOf('.');

                if (index > -1 && w.Length - index == 2)
                {
                    index = editor.Caret.Offset - 2;
                }
                else
                {
                    index = editor.Caret.Offset;
                }

                result = ef.FindExpression(editor.Document.Text, index);
                LoggingService.Debug("CC: After dot, result=" + result + ", context=" + result.Context);
                if (ShowCompletion(result, editor, ch))
                {
                    return(CodeCompletionKeyPressResult.Completed);
                }
                else
                {
                    return(CodeCompletionKeyPressResult.None);
                }

            case '@':
                if (editor.Caret.Offset > 0 && editor.Document.GetCharAt(editor.Caret.Offset - 1) == '.')
                {
                    return(CodeCompletionKeyPressResult.None);
                }
                goto default;

            case ' ':
                editor.Document.Insert(editor.Caret.Offset, " ");
                result = ef.FindExpression(editor.Document.Text, editor.Caret.Offset);

                string word = editor.GetWordBeforeCaret().Trim();
                if (word.Equals("overrides", StringComparison.OrdinalIgnoreCase) || word.Equals("return", StringComparison.OrdinalIgnoreCase) || !LiteralMayFollow((BitArray)result.Tag) && !OperatorMayFollow((BitArray)result.Tag) && ExpressionContext.IdentifierExpected != result.Context)
                {
                    LoggingService.Debug("CC: After space, result=" + result + ", context=" + result.Context);
                    ShowCompletion(result, editor, ch);
                }
                return(CodeCompletionKeyPressResult.EatKey);

            default:
                if (CodeCompletionOptions.CompleteWhenTyping)
                {
                    int  cursor   = editor.Caret.Offset;
                    char prevChar = cursor > 1 ? editor.Document.GetCharAt(cursor - 1) : ' ';
                    char ppChar   = cursor > 2 ? editor.Document.GetCharAt(cursor - 2) : ' ';

                    result = ef.FindExpression(editor.Document.Text, cursor);

                    if ((result.Context != ExpressionContext.IdentifierExpected && char.IsLetter(ch)) &&
                        (!char.IsLetterOrDigit(prevChar) && prevChar != '.'))
                    {
                        if (prevChar == '@' && ppChar == '.')
                        {
                            return(CodeCompletionKeyPressResult.None);
                        }
                        if (IsTypeCharacter(ch, prevChar))
                        {
                            return(CodeCompletionKeyPressResult.None);
                        }
                        if (prevChar == '_')
                        {
                            result.Expression = '_' + result.Expression;
                            result.Region     = new DomRegion(result.Region.BeginLine, result.Region.BeginColumn - 1, result.Region.EndLine, result.Region.EndColumn);
                        }
                        LoggingService.Debug("CC: Beginning to type a word, result=" + result + ", context=" + result.Context);
                        ShowCompletion(result, editor, ch);
                        return(CodeCompletionKeyPressResult.CompletedIncludeKeyInCompletion);
                    }
                }
                break;
            }

            return(CodeCompletionKeyPressResult.None);
        }