private bool ReformatForSmartEnter(string dummyText, ITextControl textControl, IFile file, TreeTextRange reparseTreeOffset, TreeOffset lBraceTreePos, TreeOffset rBraceTreePos, bool insertEnterAfter = false)
        {
            // insert dummy text and reformat
            TreeOffset newCaretPos;
            var        codeFormatter = GetCodeFormatter(file);

            using (PsiTransactionCookie.CreateAutoCommitCookieWithCachesUpdate(PsiServices, "Typing assist"))
            {
                string newLine      = Environment.NewLine;
                string textToInsert = newLine + dummyText;
                if (insertEnterAfter)
                {
                    textToInsert = textToInsert + newLine;
                }
                file = file.ReParse(reparseTreeOffset, textToInsert);
                if (file == null)
                {
                    return(false);
                }

                ITreeNode lBraceNode = file.FindTokenAt(lBraceTreePos);
                if (lBraceNode == null)
                {
                    return(false);
                }

                var dummyNode = file.FindTokenAt(reparseTreeOffset.StartOffset + newLine.Length) as ITokenNode;

                var languageService = file.Language.LanguageService();
                if (languageService == null)
                {
                    return(false);
                }

                while (dummyNode != null && languageService.IsFilteredNode(dummyNode))
                {
                    dummyNode = dummyNode.GetNextToken();
                }

                if (dummyNode == null)
                {
                    return(false);
                }

                var rBraceNode = file.FindTokenAt(rBraceTreePos + newLine.Length + dummyText.Length + (insertEnterAfter ? newLine.Length : 0));

                var boundSettingsStore = SettingsStore.BindToContextTransient(textControl.ToContextRange());

                codeFormatter.Format(lBraceNode, CodeFormatProfile.DEFAULT, null, boundSettingsStore);
                codeFormatter.Format(
                    rBraceNode.FindFormattingRangeToLeft(),
                    rBraceNode,
                    CodeFormatProfile.DEFAULT,
                    null,
                    boundSettingsStore);
                codeFormatter.Format(lBraceNode.Parent, CodeFormatProfile.INDENT, null);

                newCaretPos = dummyNode.GetTreeStartOffset();
                file        = file.ReParse(new TreeTextRange(newCaretPos, newCaretPos + dummyText.Length), "");
                Assertion.Assert(file != null, "file != null");
            }

            // dposition cursor
            DocumentRange newCaretPosition = file.GetDocumentRange(newCaretPos);

            if (newCaretPosition.IsValid())
            {
                textControl.Caret.MoveTo(newCaretPosition.TextRange.StartOffset, CaretVisualPlacement.DontScrollIfVisible);
            }

            return(true);
        }
        private void DoSmartIndentOnEnter(ITextControl textControl)
        {
            var originalOffset = textControl.Caret.Offset();

            var offset     = TextControlToLexer(textControl, originalOffset);
            var mixedLexer = GetCachingLexer(textControl);

            // if there is something on that line, then use existing text
            if (offset <= 0 || !mixedLexer.FindTokenAt(offset - 1))
            {
                return;
            }

            if (mixedLexer.TokenType == PsiTokenType.C_STYLE_COMMENT || mixedLexer.TokenType == PsiTokenType.STRING_LITERAL)
            {
                return;
            }

            if (offset <= 0 || !mixedLexer.FindTokenAt(offset))
            {
                return;
            }

            while (mixedLexer.TokenType == PsiTokenType.WHITE_SPACE)
            {
                mixedLexer.Advance();
            }

            offset = mixedLexer.TokenType == null ? offset : mixedLexer.TokenStart;
            var extraText = (mixedLexer.TokenType == PsiTokenType.NEW_LINE || mixedLexer.TokenType == null) ? "foo " : String.Empty;

            var projectItem = textControl.Document.GetPsiSourceFile(Solution);

            if (projectItem == null || !projectItem.IsValid())
            {
                return;
            }

            using (PsiManager.GetInstance(Solution).DocumentTransactionManager.CreateTransactionCookie(DefaultAction.Commit, "Typing assist"))
            {
                // If the new line is empty, the do default indentation
                int lexerOffset = offset;
                if (extraText.Length > 0)
                {
                    textControl.Document.InsertText(lexerOffset, extraText);
                }

                PsiServices.PsiManager.CommitAllDocuments();
                var file = projectItem.GetPsiFile <PsiLanguage>(new DocumentRange(textControl.Document, offset));

                if (file == null)
                {
                    return;
                }

                var rangeInJsTree = file.Translate(new DocumentOffset(textControl.Document, offset));

                if (!rangeInJsTree.IsValid())
                {
                    if (extraText.Length > 0)
                    {
                        textControl.Document.DeleteText(new TextRange(lexerOffset, lexerOffset + extraText.Length));
                    }
                    return;
                }

                var tokenNode = file.FindTokenAt(rangeInJsTree) as ITokenNode;
                if (tokenNode == null)
                {
                    if (extraText.Length > 0)
                    {
                        textControl.Document.DeleteText(new TextRange(lexerOffset, lexerOffset + extraText.Length));
                    }
                    return;
                }

                PsiCodeFormatter codeFormatter = GetCodeFormatter(file);
                int offsetInToken = rangeInJsTree.Offset - tokenNode.GetTreeStartOffset().Offset;

                using (PsiTransactionCookie.CreateAutoCommitCookieWithCachesUpdate(PsiServices, "Typing assist"))
                {
                    Lifetimes.Using(
                        lifetime =>
                    {
                        var boundSettingsStore = SettingsStore.CreateNestedTransaction(lifetime, "PsiTypingAssist").BindToContextTransient(textControl.ToContextRange());
                        var prevToken          = tokenNode.GetPrevToken();
                        if (prevToken == null)
                        {
                            return;
                        }

                        if (tokenNode.Parent is IParenExpression || prevToken.Parent is IParenExpression)
                        {
                            var node = tokenNode.Parent;
                            if (prevToken.Parent is IParenExpression)
                            {
                                node = prevToken.Parent;
                            }
                            codeFormatter.Format(node.FirstChild, node.LastChild,
                                                 CodeFormatProfile.DEFAULT, NullProgressIndicator.Instance, boundSettingsStore);
                        }
                        else
                        {
                            codeFormatter.Format(prevToken, tokenNode,
                                                 CodeFormatProfile.INDENT, NullProgressIndicator.Instance, boundSettingsStore);
                        }
                    });
                    offset = file.GetDocumentRange(tokenNode.GetTreeStartOffset()).TextRange.StartOffset +
                             offsetInToken;
                }

                if (extraText.Length > 0)
                {
                    lexerOffset = offset;
                    textControl.Document.DeleteText(new TextRange(lexerOffset, lexerOffset + extraText.Length));
                }
            }

            textControl.Caret.MoveTo(offset, CaretVisualPlacement.DontScrollIfVisible);
        }