private static void AppendTokenEnsureWhiteSpacesAround()

in src/LanguageServer/Impl/Formatting/LineFormatter.cs [396:551]


        private static void AppendTokenEnsureWhiteSpacesAround(StringBuilder builder, TokenExt token)
            => builder.EnsureEndsWithWhiteSpace()
            .Append(token)
            .EnsureEndsWithWhiteSpace();

        private class TokenExt {
            public TokenExt(Token token, string precedingWhitespace, IndexSpan span, int line, bool isMultiLine,
                TokenExt prev) {
                Token = token;
                PrecedingWhitespace = precedingWhitespace;
                Span = span;
                Line = line;
                Prev = prev;
                IsMultilineString = IsString && isMultiLine;
            }

            public Token Token { get; }
            public IndexSpan Span { get; }
            public int Line { get; }
            public TokenExt Inside { get; set; }
            public TokenExt Prev { get; }
            public TokenExt Next { get; set; }
            public string PrecedingWhitespace { get; }
            public bool IsMultilineString { get; }

            public TokenKind Kind => Token.Kind;

            public override string ToString() => Token.VerbatimImage;

            public bool IsIgnored => Is(TokenKind.NewLine, TokenKind.NLToken, TokenKind.Indent, TokenKind.Dedent, TokenKind.ExplicitLineJoin);

            public bool IsOpen => Is(TokenKind.LeftBrace, TokenKind.LeftBracket, TokenKind.LeftParenthesis);

            public bool IsClose => Is(TokenKind.RightBrace, TokenKind.RightBracket, TokenKind.RightParenthesis);

            public bool IsColonOrComma => Is(TokenKind.Colon, TokenKind.Comma);

            public bool MatchesClose(TokenExt other) {
                switch (Kind) {
                    case TokenKind.LeftBrace:
                        return other.Kind == TokenKind.RightBrace;
                    case TokenKind.LeftBracket:
                        return other.Kind == TokenKind.RightBracket;
                    case TokenKind.LeftParenthesis:
                        return other.Kind == TokenKind.RightParenthesis;
                }

                return false;
            }

            public bool IsOperator => Token is OperatorToken || Is(TokenKind.Dot, TokenKind.Assign, TokenKind.Twiddle);

            public bool IsUnaryOp => Is(TokenKind.Add, TokenKind.Subtract, TokenKind.Twiddle);

            public bool IsInsideFunctionArgs => (Inside?.Kind == TokenKind.LeftParenthesis && Inside.PrevNonIgnored?.Kind == TokenKind.Name) || (Inside?.Kind == TokenKind.KeywordLambda);

            public bool IsNumber => Kind == TokenKind.Constant && Token != Tokens.NoneToken && !(Token.Value is string || Token.Value is AsciiString);

            public bool IsKeyword => (Kind >= TokenKind.FirstKeyword && Kind <= TokenKind.LastKeyword) || Kind == TokenKind.KeywordAsync || Kind == TokenKind.KeywordAwait;

            public bool IsString => Kind == TokenKind.FString // TODO: format inside fstrings
                || (Kind == TokenKind.Constant && Token != Tokens.NoneToken && (Token.Value is string || Token.Value is AsciiString));

            public bool IsSimpleSliceToLeft {
                get {
                    if (Kind != TokenKind.Colon) {
                        return false;
                    }

                    var a = PrevNonIgnored;
                    var b = a?.PrevNonIgnored;
                    var c = b?.PrevNonIgnored;

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

                    if (a.Is(TokenKind.LeftBracket, TokenKind.Colon)) {
                        return true;
                    }

                    if ((!a.IsNumber && a.Kind != TokenKind.Name) || b == null) {
                        return false;
                    }

                    if (b.Is(TokenKind.LeftBracket, TokenKind.Colon, TokenKind.Comma)) {
                        return true;
                    }

                    if (!b.IsUnaryOp || c == null) {
                        return false;
                    }

                    return c.Is(TokenKind.LeftBracket, TokenKind.Colon, TokenKind.Comma);
                }
            }

            public bool IsSimpleSliceToRight {
                get {
                    if (Kind != TokenKind.Colon) {
                        return false;
                    }

                    var a = NextNonIgnored;
                    var b = a?.NextNonIgnored;
                    var c = b?.NextNonIgnored;

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

                    if (a.Is(TokenKind.RightBracket, TokenKind.Colon, TokenKind.Comma)) {
                        return true;
                    }

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

                    if (a.IsUnaryOp) {
                        if (c == null) {
                            return false;
                        }
                        return (b.IsNumber || b.Kind == TokenKind.Name) && c.Is(TokenKind.RightBracket, TokenKind.Colon, TokenKind.Comma);
                    }

                    return (a.IsNumber || a.Kind == TokenKind.Name) && b.Is(TokenKind.RightBracket, TokenKind.Colon, TokenKind.Comma);
                }
            }

            public TokenExt PrevNonIgnored {
                get {
                    if (Prev != null) {
                        if (Prev.IsIgnored) {
                            return Prev.PrevNonIgnored;
                        }
                        return Prev;
                    }
                    return null;
                }
            }

            public TokenExt NextNonIgnored {
                get {
                    if (Next != null) {
                        if (Next.IsIgnored) {
                            return Next.NextNonIgnored;
                        }
                        return Next;
                    }
                    return null;
                }
            }

            private bool Is(params TokenKind[] kinds) => kinds.Contains(Kind);
        }