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); } }
protected override bool CanRemoveParentheses( ParenthesizedPatternSyntax parenthesizedExpression, SemanticModel semanticModel, CancellationToken cancellationToken, out PrecedenceKind precedence, out bool clarifiesPrecedence) { return(CanRemoveParenthesesHelper(parenthesizedExpression, out precedence, out clarifiesPrecedence)); }
private ImmutableArray <SyntaxNodeOrToken> GetExpressionsAndOperators( PrecedenceKind precedence, TBinaryExpressionSyntax binaryExpr) { var result = ArrayBuilder <SyntaxNodeOrToken> .GetInstance(); AddExpressionsAndOperators(precedence, binaryExpr, result); return(result.ToImmutableAndFree()); }
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 {