Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* InsertParenthesesVisitor.java
*
* Copyright (c) 2013 Mike Strobel
*
* This source code is based on Mono.Cecil from Jb Evain, Copyright (c) Jb Evain;
* and ILSpy/ICSharpCode from SharpDevelop, Copyright (c) AlphaSierraPapa.
*
* This source code is subject to terms and conditions of the Apache License, Version 2.0.
* A copy of the license can be found in the License.html file at the root of this distribution.
* By using this source code in any fashion, you are agreeing to be bound by the terms of the
* Apache License, Version 2.0.
*
* You must not remove this notice, or any other, from this software.
*/
package com.strobel.decompiler.languages.java.ast;
import com.strobel.functions.Function;
import com.strobel.util.ContractUtils;
public final class InsertParenthesesVisitor extends DepthFirstAstVisitor {
private final static int PRIMARY = 16;
private final static int CAST = 15;
private final static int UNARY = 14;
private static final int MULTIPLICATIVE = 13;
private static final int ADDITIVE = 12;
private static final int SHIFT = 11;
private final static int RELATIONAL_AND_TYPE_TESTING = 10;
private final static int EQUALITY = 9;
private static final int BITWISE_AND = 8;
private static final int EXCLUSIVE_OR = 7;
private static final int BITWISE_OR = 6;
private static final int LOGICAL_AND = 5;
private static final int LOGICAL_OR = 4;
private final static int CONDITIONAL = 2;
private final static int ASSIGNMENT = 1;
private final static Function PARENTHESIZE_FUNCTION = new Function() {
@Override
public AstNode apply(final AstNode input) {
return new ParenthesizedExpression((Expression) input);
}
};
private boolean _insertParenthesesForReadability = true;
public final boolean getInsertParenthesesForReadability() {
return _insertParenthesesForReadability;
}
public final void setInsertParenthesesForReadability(final boolean insertParenthesesForReadability) {
_insertParenthesesForReadability = insertParenthesesForReadability;
}
private static int getPrecedence(final Expression e) {
if (e instanceof UnaryOperatorExpression) {
final UnaryOperatorExpression unary = (UnaryOperatorExpression) e;
if (unary.getOperator() == UnaryOperatorType.POST_DECREMENT ||
unary.getOperator() == UnaryOperatorType.POST_INCREMENT) {
return PRIMARY;
}
return UNARY;
}
if (e instanceof CastExpression) {
return CAST;
}
if (e instanceof BinaryOperatorExpression) {
final BinaryOperatorExpression binary = (BinaryOperatorExpression) e;
switch (binary.getOperator()) {
case MULTIPLY:
case DIVIDE:
case MODULUS:
return MULTIPLICATIVE;
case ADD:
case SUBTRACT:
return ADDITIVE;
case SHIFT_LEFT:
case SHIFT_RIGHT:
case UNSIGNED_SHIFT_RIGHT:
return SHIFT;
case GREATER_THAN:
case GREATER_THAN_OR_EQUAL:
case LESS_THAN:
case LESS_THAN_OR_EQUAL:
return RELATIONAL_AND_TYPE_TESTING;
case EQUALITY:
case INEQUALITY:
return EQUALITY;
case BITWISE_AND:
return BITWISE_AND;
case EXCLUSIVE_OR:
return EXCLUSIVE_OR;
case BITWISE_OR:
return BITWISE_OR;
case LOGICAL_AND:
return LOGICAL_AND;
case LOGICAL_OR:
return LOGICAL_OR;
default:
throw ContractUtils.unsupported();
}
}
if (e instanceof InstanceOfExpression) {
return RELATIONAL_AND_TYPE_TESTING;
}
if (e instanceof ConditionalExpression) {
return CONDITIONAL;
}
if (e instanceof AssignmentExpression || e instanceof LambdaExpression) {
return ASSIGNMENT;
}
return PRIMARY;
}
private static BinaryOperatorType getBinaryOperatorType(final Expression e) {
if (e instanceof BinaryOperatorExpression) {
return ((BinaryOperatorExpression) e).getOperator();
}
return null;
}
private static void parenthesizeIfRequired(final Expression expression, final int minimumPrecedence) {
if (getPrecedence(expression) < minimumPrecedence) {
parenthesize(expression);
}
}
private static void parenthesize(final Expression expression) {
expression.replaceWith(PARENTHESIZE_FUNCTION);
}
private static boolean canTypeBeMisinterpretedAsExpression(final AstType type) {
return type instanceof SimpleType;
}
@Override
public Void visitMemberReferenceExpression(final MemberReferenceExpression node, final Void data) {
parenthesizeIfRequired(node.getTarget(), PRIMARY);
return super.visitMemberReferenceExpression(node, data);
}
@Override
public Void visitInvocationExpression(final InvocationExpression node, final Void data) {
parenthesizeIfRequired(node.getTarget(), PRIMARY);
return super.visitInvocationExpression(node, data);
}
@Override
public Void visitIndexerExpression(final IndexerExpression node, final Void data) {
parenthesizeIfRequired(node.getTarget(), PRIMARY);
if (node.getTarget() instanceof ArrayCreationExpression) {
final ArrayCreationExpression arrayCreation = (ArrayCreationExpression) node.getTarget();
if (_insertParenthesesForReadability || arrayCreation.getInitializer().isNull()) {
// require parentheses for "(new int[1])[0]"
parenthesize(arrayCreation);
}
}
return super.visitIndexerExpression(node, data);
}
@Override
public Void visitUnaryOperatorExpression(final UnaryOperatorExpression node, final Void data) {
final Expression child = node.getExpression();
parenthesizeIfRequired(child, getPrecedence(node));
if (_insertParenthesesForReadability && child instanceof UnaryOperatorExpression) {
parenthesize(child);
}
return super.visitUnaryOperatorExpression(node, data);
}
@Override
public Void visitCastExpression(final CastExpression node, final Void data) {
final Expression child = node.getExpression();
parenthesizeIfRequired(child, UNARY);
if (child instanceof UnaryOperatorExpression) {
final UnaryOperatorExpression childUnary = (UnaryOperatorExpression) child;
if (childUnary.getOperator() != UnaryOperatorType.BITWISE_NOT &&
childUnary.getOperator() != UnaryOperatorType.NOT) {
if (canTypeBeMisinterpretedAsExpression(node.getType())) {
parenthesize(child);
}
}
}
if (child instanceof PrimitiveExpression) {
final PrimitiveExpression primitive = (PrimitiveExpression) child;
final Object primitiveValue = primitive.getValue();
if (primitiveValue instanceof Number) {
final Number number = (Number) primitiveValue;
if (primitiveValue instanceof Float || primitiveValue instanceof Double) {
if (number.doubleValue() < 0d) {
parenthesize(child);
}
}
else if (number.longValue() < 0L) {
parenthesize(child);
}
}
}
return super.visitCastExpression(node, data);
}
@Override
public Void visitBinaryOperatorExpression(final BinaryOperatorExpression node, final Void data) {
final int precedence = getPrecedence(node);
if (_insertParenthesesForReadability && precedence < EQUALITY) {
if (getBinaryOperatorType(node.getLeft()) == node.getOperator()) {
parenthesizeIfRequired(node.getLeft(), precedence);
}
else {
parenthesizeIfRequired(node.getLeft(), EQUALITY);
}
parenthesizeIfRequired(node.getRight(), EQUALITY);
}
else {
parenthesizeIfRequired(node.getLeft(), precedence);
parenthesizeIfRequired(node.getRight(), precedence + 1);
}
return super.visitBinaryOperatorExpression(node, data);
}
@Override
public Void visitInstanceOfExpression(final InstanceOfExpression node, final Void data) {
if (_insertParenthesesForReadability) {
parenthesizeIfRequired(node.getExpression(), PRIMARY);
}
else {
parenthesizeIfRequired(node.getExpression(), RELATIONAL_AND_TYPE_TESTING);
}
return super.visitInstanceOfExpression(node, data);
}
@Override
public Void visitConditionalExpression(final ConditionalExpression node, final Void data) {
//
// Associativity here is a bit tricky:
//
// (a ? b : c ? d : e) == (a ? b : (c ? d : e))
// (a ? b ? c : d : e) == (a ? (b ? c : d) : e)
//
// Only ((a ? b : c) ? d : e) strictly needs the additional parentheses.
//
if (_insertParenthesesForReadability) {
// Precedence of ?: can be confusing; so always put parentheses in nice-looking mode.
parenthesizeIfRequired(node.getCondition(), PRIMARY);
parenthesizeIfRequired(node.getTrueExpression(), PRIMARY);
parenthesizeIfRequired(node.getFalseExpression(), PRIMARY);
}
else {
parenthesizeIfRequired(node.getCondition(), CONDITIONAL + 1);
parenthesizeIfRequired(node.getTrueExpression(), CONDITIONAL);
parenthesizeIfRequired(node.getFalseExpression(), CONDITIONAL);
}
return super.visitConditionalExpression(node, data);
}
@Override
public Void visitAssignmentExpression(final AssignmentExpression node, final Void data) {
parenthesizeIfRequired(node.getLeft(), ASSIGNMENT + 1);
if (_insertParenthesesForReadability) {
parenthesizeIfRequired(node.getRight(), RELATIONAL_AND_TYPE_TESTING + 1);
}
else {
parenthesizeIfRequired(node.getRight(), ASSIGNMENT);
}
return super.visitAssignmentExpression(node, data);
}
}