From d0f34b145043b83073079b8b265bb563bbf69f6b Mon Sep 17 00:00:00 2001 From: xtaisafelix <95292143+xtaisafelix@users.noreply.github.com> Date: Tue, 30 Nov 2021 12:43:50 -0300 Subject: [PATCH] Warwn on logical operators Warn on logical operators AND and OR expressions without explicit parenthesization --- .../com/facebook/coresql/parser/AstNode.java | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/parser/src/main/java/com/facebook/coresql/parser/AstNode.java b/parser/src/main/java/com/facebook/coresql/parser/AstNode.java index e5f6df8..54e87f7 100644 --- a/parser/src/main/java/com/facebook/coresql/parser/AstNode.java +++ b/parser/src/main/java/com/facebook/coresql/parser/AstNode.java @@ -13,6 +13,10 @@ */ package com.facebook.coresql.parser; +import com.facebook.coresql.linter.warning.WarningCollector; + +import java.io.StringReader; + public class AstNode extends com.facebook.coresql.parser.SimpleNode { @@ -91,4 +95,58 @@ public String toString(String prefix) return super.toString(prefix) + " (" + getLocation().toString() + ")" + (NumChildren() == 0 ? " (" + beginToken.image + ")" : ""); } + + @Override + public AstNode visitLogicalBinary(com.facebook.coresql.parser.SqlParser context) + { + LogicalBinaryExpression.Operator operator = getLogicalBinaryOperator(context.operator); + boolean warningForMixedAndOr = false; + Expression left = (Expression) visit(context.left); + Expression right = (Expression) visit(context.right); + + if (operator.equals(LogicalBinaryExpression.Operator.OR) && + (mixedAndOrOperatorParenthesisCheck(right, context.right, LogicalBinaryExpression.Operator.AND) || + mixedAndOrOperatorParenthesisCheck(left, context.left, LogicalBinaryExpression.Operator.AND))) { + warningForMixedAndOr = true; + } + + if (operator.equals(LogicalBinaryExpression.Operator.AND) && + (mixedAndOrOperatorParenthesisCheck(right, context.right, LogicalBinaryExpression.Operator.OR) || + mixedAndOrOperatorParenthesisCheck(left, context.left, LogicalBinaryExpression.Operator.OR))) { + warningForMixedAndOr = true; + } + + if (warningForMixedAndOr) { + warningConsumer.accept(new ParsingWarning( + "The Query contains OR and AND operator without proper parenthesis. " + + "Make sure the operators are guarded by parenthesis in order " + + "to fetch logically correct results", + context.getStart().getLine(), context.getStart().getCharPositionInLine())); + } + + return new LogicalBinaryExpression( + getLocation(context.operator), + getLogicalBinaryOperator(context.operator), + (Expression) visit(context.left), + (Expression) visit(context.right)); + operator, + left, + right); + } + + private boolean mixedAndOrOperatorParenthesisCheck(Expression expression, SqlBaseParser.BooleanExpressionContext node, LogicalBinaryExpression.Operator operator) + { + if (expression instanceof LogicalBinaryExpression) { + if (((LogicalBinaryExpression) expression).getOperator().equals(operator)) { + if (node.children.get(0) instanceof SqlBaseParser.ValueExpressionDefaultContext) { + return !(((SqlBaseParser.PredicatedContext) node).valueExpression().getChild(0) instanceof + SqlBaseParser.ParenthesizedExpressionContext); + } + else { + return true; + } + } + } + return false; + } }