private static bool NeedAutoinsertCloseBracket(CachingLexer lexer)
        {
            using (LexerStateCookie.Create(lexer))
            {
                TokenNodeType typedToken = lexer.TokenType;

                // find the leftmost non-closed bracket (including typed) of typed class so that there are no opened brackets of other type
                var           bracketMatcher = new PsiBracketMatcher();
                TokenNodeType tokenType      = typedToken;

                int leftParenthPos = lexer.CurrentPosition;
                do
                {
                    if (tokenType == typedToken && bracketMatcher.IsStackEmpty())
                    {
                        leftParenthPos = lexer.CurrentPosition;
                    }
                    else if (!bracketMatcher.ProceedStack(tokenType))
                    {
                        break;
                    }
                    lexer.Advance(-1);
                } while ((tokenType = lexer.TokenType) != null);

                // Try to find the matched pair bracket
                lexer.CurrentPosition = leftParenthPos;

                return(!bracketMatcher.FindMatchingBracket(lexer));
            }
        }
        private bool NeedSkipCloseBracket(CachingLexer lexer, char charTyped)
        {
            // check if the next token matches the typed char
            TokenNodeType nextToken = lexer.TokenType;

            if ((charTyped == ')' && nextToken != PsiTokenType.RPARENTH) ||
                (charTyped == ']' && nextToken != PsiTokenType.RBRACKET) ||
                (charTyped == '}' && nextToken != PsiTokenType.RBRACE))
            {
                return(false);
            }

            // find the leftmost non-closed bracket (excluding typed) of typed class so that there are no opened brackets of other type
            var           bracketMatcher  = new PsiBracketMatcher();
            TokenNodeType searchTokenType = charTyped == ')'
        ? PsiTokenType.LPARENTH
        : charTyped == ']' ? PsiTokenType.LBRACKET : PsiTokenType.LBRACE;
            int?          leftParenthPos = null;
            TokenNodeType tokenType;

            for (lexer.Advance(-1); (tokenType = lexer.TokenType) != null; lexer.Advance(-1))
            {
                if (tokenType == searchTokenType && bracketMatcher.IsStackEmpty())
                {
                    leftParenthPos = lexer.CurrentPosition;
                }
                else if (!bracketMatcher.ProceedStack(tokenType))
                {
                    break;
                }
            }

            // proceed with search result
            if (leftParenthPos == null)
            {
                return(false);
            }
            lexer.CurrentPosition = leftParenthPos.Value;
            return(bracketMatcher.FindMatchingBracket(lexer));
        }