private void AddExpressionsAndOperators(
     PrecedenceKind precedence,
     SyntaxNode expr,
     ArrayBuilder <SyntaxNodeOrToken> result
     )
 {
     if (
         expr is TBinaryExpressionSyntax &&
         precedence == _precedenceService.GetPrecedenceKind(expr)
         )
     {
         _syntaxFacts.GetPartsOfBinaryExpression(
             expr,
             out var left,
             out var opToken,
             out var right
             );
         AddExpressionsAndOperators(precedence, left, result);
         result.Add(opToken);
         AddExpressionsAndOperators(precedence, right, result);
     }
     else
     {
         result.Add(expr);
     }
 }
Exemple #2
0
 protected override bool CanRemoveParentheses(
     ParenthesizedPatternSyntax parenthesizedExpression,
     SemanticModel semanticModel, CancellationToken cancellationToken,
     out PrecedenceKind precedence, out bool clarifiesPrecedence)
 {
     return(CanRemoveParenthesesHelper(parenthesizedExpression, out precedence, out clarifiesPrecedence));
 }
Exemple #3
0
        private ImmutableArray <SyntaxNodeOrToken> GetExpressionsAndOperators(
            PrecedenceKind precedence, TBinaryExpressionSyntax binaryExpr)
        {
            var result = ArrayBuilder <SyntaxNodeOrToken> .GetInstance();

            AddExpressionsAndOperators(precedence, binaryExpr, result);
            return(result.ToImmutableAndFree());
        }
Exemple #4
0
        public static bool CanRemoveParenthesesHelper(
            ParenthesizedPatternSyntax parenthesizedPattern,
            out PrecedenceKind parentPrecedenceKind,
            out bool clarifiesPrecedence
            )
        {
            var result = parenthesizedPattern.CanRemoveParentheses();

            if (!result)
            {
                parentPrecedenceKind = default;
                clarifiesPrecedence  = false;
                return(false);
            }

            var inner           = parenthesizedPattern.Pattern;
            var innerPrecedence = inner.GetOperatorPrecedence();
            var innerIsSimple   =
                innerPrecedence == OperatorPrecedence.Primary ||
                innerPrecedence == OperatorPrecedence.None;

            if (!(parenthesizedPattern.Parent is PatternSyntax))
            {
                // We're parented by something not a pattern.  i.e. `x is (...)` or `case (...)`.
                // These parentheses are never needed for clarity and can always be removed.
                parentPrecedenceKind = PrecedenceKind.Other;
                clarifiesPrecedence  = false;
                return(true);
            }

            if (!(parenthesizedPattern.Parent is BinaryPatternSyntax parentPattern))
            {
                // We're parented by something other than a BinaryPattern.  These parentheses are never needed for
                // clarity and can always be removed.
                parentPrecedenceKind = PrecedenceKind.Other;
                clarifiesPrecedence  = false;
                return(true);
            }

            // We're parented by something binary-like.
            parentPrecedenceKind = CSharpPatternPrecedenceService.Instance.GetPrecedenceKind(
                parentPattern
                );

            // Precedence is clarified any time we have expression with different precedence
            // (and the inner expression is not a primary expression).  in other words, this
            // is helps clarify precedence:
            //
            //      a or (b and c)
            //
            // However, this does not:
            //
            //      a or (b)
            clarifiesPrecedence =
                !innerIsSimple && parentPattern.GetOperatorPrecedence() != innerPrecedence;
            return(true);
        }
 protected override bool CanRemoveParentheses(
     ParenthesizedExpressionSyntax parenthesizedExpression,
     SemanticModel semanticModel,
     out PrecedenceKind precedence,
     out bool clarifiesPrecedence
 )
 {
     return CanRemoveParenthesesHelper(
         parenthesizedExpression,
         semanticModel,
         out precedence,
         out clarifiesPrecedence
     );
 }
            > GetLanguageOption(PrecedenceKind precedenceKind)
        {
            switch (precedenceKind)
            {
            case PrecedenceKind.Arithmetic:
            case PrecedenceKind.Shift:
            case PrecedenceKind.Bitwise:
                return(CodeStyleOptions2.ArithmeticBinaryParentheses);

            case PrecedenceKind.Relational:
            case PrecedenceKind.Equality:
                return(CodeStyleOptions2.RelationalBinaryParentheses);

            case PrecedenceKind.Logical:
            case PrecedenceKind.Coalesce:
                return(CodeStyleOptions2.OtherBinaryParentheses);

            case PrecedenceKind.Other:
                return(CodeStyleOptions2.OtherParentheses);
            }

            throw ExceptionUtilities.UnexpectedValue(precedenceKind);
        }
 protected abstract bool CanRemoveParentheses(
     TParenthesizedExpressionSyntax parenthesizedExpression, SemanticModel semanticModel,
     out PrecedenceKind precedence, out bool clarifiesPrecedence);
        public static bool CanRemoveParenthesesHelper(
            ParenthesizedExpressionSyntax parenthesizedExpression, SemanticModel semanticModel,
            out PrecedenceKind parentPrecedenceKind, out bool clarifiesPrecedence)
        {
            var result = parenthesizedExpression.CanRemoveParentheses(semanticModel);

            if (!result)
            {
                parentPrecedenceKind = default;
                clarifiesPrecedence  = false;
                return(false);
            }

            var inner           = parenthesizedExpression.Expression;
            var innerPrecedence = inner.GetOperatorPrecedence();
            var innerIsSimple   = innerPrecedence == OperatorPrecedence.Primary ||
                                  innerPrecedence == OperatorPrecedence.None;

            ExpressionSyntax parentExpression;

            switch (parenthesizedExpression.Parent)
            {
            case ConditionalExpressionSyntax _:
                // If our parent is a conditional, then only remove parens if the inner
                // expression is a primary. i.e. it's ok to remove any of the following:
                //
                //      (a()) ? (b.length) : (c[0])
                //
                // But we shouldn't remove parens for anything more complex like:
                //
                //      ++a ? b + c : d << e
                //
                parentPrecedenceKind = PrecedenceKind.Other;
                clarifiesPrecedence  = false;
                return(innerIsSimple);

            case BinaryExpressionSyntax binaryExpression:
                parentExpression = binaryExpression;
                break;

            case IsPatternExpressionSyntax isPatternExpression:
                // on the left side of an 'x is pat' expression
                parentExpression = isPatternExpression;
                break;

            case ConstantPatternSyntax constantPattern when constantPattern.Parent is IsPatternExpressionSyntax isPatternExpression:
                // on the right side of an 'x is const_pattern' expression
                parentExpression = isPatternExpression;
                break;

            default:
                parentPrecedenceKind = PrecedenceKind.Other;
                clarifiesPrecedence  = false;
                return(true);
            }

            // We're parented by something binary-like.
            parentPrecedenceKind = CSharpExpressionPrecedenceService.Instance.GetPrecedenceKind(parentExpression);

            // Precedence is clarified any time we have expression with different precedence
            // (and the inner expression is not a primary expression).  in other words, this
            // is helps clarify precedence:
            //
            //      a + (b * c)
            //
            // However, this does not:
            //
            //      a + (b.Length)
            clarifiesPrecedence = !innerIsSimple &&
                                  parentExpression.GetOperatorPrecedence() != innerPrecedence;
            return(true);
        }
 protected static CodeStyleOption2 <ParenthesesPreference> GetLanguageOption(AnalyzerOptionsProvider options, PrecedenceKind precedenceKind)
 => precedenceKind switch
 {