private static bool IsInnerExpressionContext()

in src/Bicep.LangServer/Completions/BicepCompletionContext.cs [1120:1272]


        private static bool IsInnerExpressionContext(List<SyntaxBase> matchingNodes, int offset)
        {
            if (!matchingNodes.OfType<ExpressionSyntax>().Any())
            {
                // Fail fast.
                return false;
            }

            var isBooleanOrNumberOrNull = SyntaxMatcher.IsTailMatch<Token>(matchingNodes, token => token.Type switch
            {
                TokenType.TrueKeyword => true,
                TokenType.FalseKeyword => true,
                TokenType.Integer => true,
                TokenType.NullKeyword => true,
                _ => false,
            });

            if (isBooleanOrNumberOrNull)
            {
                // Don't provide completions for a boolean, number, or null literal because it may be confusing.
                return false;
            }

            var isInStringSegment = SyntaxMatcher.IsTailMatch<StringSyntax, Token>(matchingNodes, (_, token) => token.Type switch
            {
                // The cursor is immediately after the { character: '...${|...}...'.
                TokenType.StringLeftPiece when IsOffsetImmediatlyAfterNode(offset, token) => false,
                TokenType.StringMiddlePiece when IsOffsetImmediatlyAfterNode(offset, token) => false,
                // In other cases, we are in a string segment.
                TokenType.StringComplete => true,
                TokenType.StringLeftPiece => true,
                TokenType.StringMiddlePiece => true,
                TokenType.StringRightPiece => true,
                TokenType.MultilineString => true,
                _ => false,
            });

            if (isInStringSegment)
            {
                return false;
            }

            // var foo = true ?|:
            // var foo = true ?| :
            // var foo = true ? |:
            // var foo = true ? | :
            var isInEmptyTrueExpression = SyntaxMatcher.IsTailMatch<TernaryOperationSyntax>(
                matchingNodes,
                ternaryOperation =>
                    ternaryOperation.Question.GetPosition() <= offset &&
                    ternaryOperation.Colon.GetPosition() >= offset &&
                    ternaryOperation.TrueExpression is SkippedTriviaSyntax);

            if (isInEmptyTrueExpression)
            {
                return true;
            }

            // var foo = true ? : | <white spaces>
            var isInEmptyFalseExpression = SyntaxMatcher.IsTailMatch<TernaryOperationSyntax>(
                matchingNodes,
                ternaryOperation =>
                    ternaryOperation.Colon.GetPosition() <= offset &&
                    ternaryOperation.FalseExpression.GetPosition() >= offset &&
                    ternaryOperation.FalseExpression is SkippedTriviaSyntax);

            if (isInEmptyFalseExpression)
            {
                return true;
            }

            // It does not make sense to insert expressions at the cursor positions shown in the comments below.
            return !(
                //║{              ║{             ║|{|           ║{            ║{
                //║  foo: true |  ║ | foo: true  ║  foo: true   ║  foo: true  ║  |
                //║}              ║}             ║}             ║|}|          ║}
                SyntaxMatcher.IsTailMatch<ObjectSyntax>(matchingNodes) ||
                SyntaxMatcher.IsTailMatch<ObjectSyntax, Token>(matchingNodes) ||

                //║[         ║[        ║|[|      ║[
                //║  true |  ║ | true  ║  true   ║  true
                //║]         ║]        ║]        ║|]|
                SyntaxMatcher.IsTailMatch<ArraySyntax>(matchingNodes) ||
                SyntaxMatcher.IsTailMatch<ArraySyntax, Token>(
                    matchingNodes,
                    (arraySyntax, token) => token.Type != TokenType.NewLine || !CanInsertChildNodeAtOffset(arraySyntax, offset)) ||

                // var test = map([], ( | ) => 'asdf')
                SyntaxMatcher.IsTailMatch<VariableBlockSyntax>(matchingNodes) ||
                // var test = map([], (a|) => 'asdf')
                SyntaxMatcher.IsTailMatch<VariableBlockSyntax, LocalVariableSyntax, IdentifierSyntax, Token>(matchingNodes) ||
                // var test = map([], (|) => 'asdf')
                SyntaxMatcher.IsTailMatch<VariableBlockSyntax, Token>(matchingNodes) ||

                // func foo( | ) string => 'asdf'
                SyntaxMatcher.IsTailMatch<TypedVariableBlockSyntax>(matchingNodes) ||
                // func foo(a|) string => 'asdf'
                SyntaxMatcher.IsTailMatch<TypedVariableBlockSyntax, TypedLocalVariableSyntax, IdentifierSyntax, Token>(matchingNodes) ||
                // func foo(|) string => 'asdf'
                SyntaxMatcher.IsTailMatch<TypedVariableBlockSyntax, Token>(matchingNodes) ||

                // var foo = ! | bar
                SyntaxMatcher.IsTailMatch<UnaryOperationSyntax>(
                    matchingNodes,
                    unaryOperation => !unaryOperation.Expression.IsOverlapping(offset)) ||

                // var foo = |!bar
                // var foo = !| bar
                SyntaxMatcher.IsTailMatch<UnaryOperationSyntax, Token>(
                    matchingNodes,
                    (unaryOperation, operatorToken) =>
                        operatorToken.GetPosition() == offset ||
                        (operatorToken.GetEndPosition() == offset && unaryOperation.Expression is not SkippedTriviaSyntax)) ||

                // var foo = 1 | + ...
                // var foo = 1 + | 2
                SyntaxMatcher.IsTailMatch<BinaryOperationSyntax>(
                    matchingNodes,
                    binaryOperation =>
                        !binaryOperation.LeftExpression.IsOverlapping(offset) &&
                        !binaryOperation.RightExpression.IsOverlapping(offset)) ||

                // var foo = 1 |+ ...
                // var foo = 1 +| 2
                SyntaxMatcher.IsTailMatch<BinaryOperationSyntax, Token>(
                    matchingNodes,
                    (binaryOperation, operatorToken) =>
                        (operatorToken.GetPosition() == offset && binaryOperation.LeftExpression is not SkippedTriviaSyntax) ||
                        (operatorToken.GetEndPosition() == offset && binaryOperation.RightExpression is not SkippedTriviaSyntax)) ||

                // var foo = true | ? ...
                // var foo = true ? | 'yes'
                // var foo = true ? 'yes' | : ...
                // var foo = true ? 'yes' : | 'no'
                SyntaxMatcher.IsTailMatch<TernaryOperationSyntax>(
                    matchingNodes,
                    ternaryOperation =>
                        !ternaryOperation.ConditionExpression.IsOverlapping(offset) &&
                        !ternaryOperation.TrueExpression.IsOverlapping(offset) &&
                        !ternaryOperation.FalseExpression.IsOverlapping(offset)) ||

                // var foo = true |? ...
                // var foo = true ?| 'yes'
                // var foo = true ? 'yes' |: ...
                // var foo = true ? 'yes' :| 'no'
                SyntaxMatcher.IsTailMatch<TernaryOperationSyntax, Token>(
                    matchingNodes,
                    (ternaryOperation, operatorToken) =>
                        (operatorToken.Type == TokenType.Question && operatorToken.GetPosition() == offset && ternaryOperation.ConditionExpression is not SkippedTriviaSyntax) ||
                        (operatorToken.Type == TokenType.Question && operatorToken.GetEndPosition() == offset && ternaryOperation.TrueExpression is not SkippedTriviaSyntax) ||
                        (operatorToken.Type == TokenType.Colon && operatorToken.GetPosition() == offset && ternaryOperation.TrueExpression is not SkippedTriviaSyntax) ||
                        (operatorToken.Type == TokenType.Colon && operatorToken.GetEndPosition() == offset && ternaryOperation.FalseExpression is not SkippedTriviaSyntax)));
        }