diff --git a/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/InsertParenthesesVisitorTests.cs b/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/InsertParenthesesVisitorTests.cs index fd044068f..5fa0b5469 100644 --- a/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/InsertParenthesesVisitorTests.cs +++ b/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/InsertParenthesesVisitorTests.cs @@ -159,7 +159,7 @@ namespace ICSharpCode.NRefactory.CSharp public void MethodCallOnQueryExpression() { Expression expr = new QueryExpression { - Clauses = new QueryClause[] { + Clauses = { new QueryFromClause { Identifier = "a", Expression = new IdentifierExpression("b") @@ -178,7 +178,7 @@ namespace ICSharpCode.NRefactory.CSharp public void SumOfQueries() { QueryExpression query = new QueryExpression { - Clauses = new QueryClause[] { + Clauses = { new QueryFromClause { Identifier = "a", Expression = new IdentifierExpression("b") @@ -206,7 +206,7 @@ namespace ICSharpCode.NRefactory.CSharp public void QueryInTypeTest() { Expression expr = new QueryExpression { - Clauses = new QueryClause[] { + Clauses = { new QueryFromClause { Identifier = "a", Expression = new IdentifierExpression("b") @@ -252,5 +252,73 @@ namespace ICSharpCode.NRefactory.CSharp Assert.AreEqual("(++a)++", InsertRequired(expr)); Assert.AreEqual("(++a)++", InsertReadable(expr)); } + + [Test] + public void Logical1() + { + Expression expr = new BinaryOperatorExpression( + new BinaryOperatorExpression( + new IdentifierExpression("a"), + BinaryOperatorType.ConditionalAnd, + new IdentifierExpression("b") + ), + BinaryOperatorType.ConditionalAnd, + new IdentifierExpression("c") + ); + + Assert.AreEqual("a && b && c", InsertRequired(expr)); + Assert.AreEqual("a && b && c", InsertReadable(expr)); + } + + [Test] + public void Logical2() + { + Expression expr = new BinaryOperatorExpression( + new IdentifierExpression("a"), + BinaryOperatorType.ConditionalAnd, + new BinaryOperatorExpression( + new IdentifierExpression("b"), + BinaryOperatorType.ConditionalAnd, + new IdentifierExpression("c") + ) + ); + + Assert.AreEqual("a && (b && c)", InsertRequired(expr)); + Assert.AreEqual("a && (b && c)", InsertReadable(expr)); + } + + [Test] + public void Logical3() + { + Expression expr = new BinaryOperatorExpression( + new IdentifierExpression("a"), + BinaryOperatorType.ConditionalOr, + new BinaryOperatorExpression( + new IdentifierExpression("b"), + BinaryOperatorType.ConditionalAnd, + new IdentifierExpression("c") + ) + ); + + Assert.AreEqual("a || b && c", InsertRequired(expr)); + Assert.AreEqual("a || (b && c)", InsertReadable(expr)); + } + + [Test] + public void Logical4() + { + Expression expr = new BinaryOperatorExpression( + new IdentifierExpression("a"), + BinaryOperatorType.ConditionalAnd, + new BinaryOperatorExpression( + new IdentifierExpression("b"), + BinaryOperatorType.ConditionalOr, + new IdentifierExpression("c") + ) + ); + + Assert.AreEqual("a && (b || c)", InsertRequired(expr)); + Assert.AreEqual("a && (b || c)", InsertReadable(expr)); + } } } diff --git a/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/InsertParenthesesVisitor.cs b/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/InsertParenthesesVisitor.cs index abdd06e63..cfa12e17a 100644 --- a/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/InsertParenthesesVisitor.cs +++ b/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/InsertParenthesesVisitor.cs @@ -186,7 +186,13 @@ namespace ICSharpCode.NRefactory.CSharp } } else { if (InsertParenthesesForReadability && precedence < Equality) { - ParenthesizeIfRequired(binaryOperatorExpression.Left, Equality); + // In readable mode, boost the priority of the left-hand side if the operator + // there isn't the same as the operator on this expression. + if (GetBinaryOperatorType(binaryOperatorExpression.Left) == binaryOperatorExpression.Operator) { + ParenthesizeIfRequired(binaryOperatorExpression.Left, precedence); + } else { + ParenthesizeIfRequired(binaryOperatorExpression.Left, Equality); + } ParenthesizeIfRequired(binaryOperatorExpression.Right, Equality); } else { // all other binary operators are left-associative @@ -197,6 +203,15 @@ namespace ICSharpCode.NRefactory.CSharp return base.VisitBinaryOperatorExpression(binaryOperatorExpression, data); } + BinaryOperatorType? GetBinaryOperatorType(Expression expr) + { + BinaryOperatorExpression boe = expr as BinaryOperatorExpression; + if (boe != null) + return boe.Operator; + else + return null; + } + public override object VisitIsExpression(IsExpression isExpression, object data) { if (InsertParenthesesForReadability) { diff --git a/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs b/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs index cf880653e..1c67668d0 100644 --- a/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs +++ b/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs @@ -566,7 +566,7 @@ namespace ICSharpCode.NRefactory.CSharp WriteKeyword("checked"); LPar(); Space(policy.WithinCheckedExpressionParantheses); - checkedExpression.AcceptVisitor(this, data); + checkedExpression.Expression.AcceptVisitor(this, data); Space(policy.WithinCheckedExpressionParantheses); RPar(); return EndNode(checkedExpression); @@ -933,7 +933,7 @@ namespace ICSharpCode.NRefactory.CSharp WriteKeyword("unchecked"); LPar(); Space(policy.WithinCheckedExpressionParantheses); - uncheckedExpression.AcceptVisitor(this, data); + uncheckedExpression.Expression.AcceptVisitor(this, data); Space(policy.WithinCheckedExpressionParantheses); RPar(); return EndNode(uncheckedExpression);