blob: 6b499e1bfdd5975b8b72469a1cd31f95fcc8560d [file] [log] [blame]
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.psi.impl.source.tree.java;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.JavaTokenType;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiPolyadicExpression;
import com.intellij.psi.impl.source.SourceTreeToPsiMap;
import com.intellij.psi.impl.source.tree.ChildRole;
import com.intellij.psi.impl.source.tree.CompositeElement;
import com.intellij.psi.impl.source.tree.ElementType;
import com.intellij.psi.impl.source.tree.JavaElementType;
import com.intellij.psi.tree.IElementType;
public class ReplaceExpressionUtil {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.java.ReplaceExpressionUtil");
public static boolean isNeedParenthesis(ASTNode oldExpr, ASTNode newExpr) {
final ASTNode oldParent = oldExpr.getTreeParent();
if (!ElementType.EXPRESSION_BIT_SET.contains(oldParent.getElementType())) return false;
int priority = getExpressionPriority(newExpr);
int parentPriority = getExpressionPriority(oldParent);
if (priority > parentPriority) return false;
IElementType i = oldParent.getElementType();
if (i == JavaElementType.ASSIGNMENT_EXPRESSION) {
return priority < parentPriority || ((CompositeElement)oldParent).getChildRole(oldExpr) == ChildRole.LOPERAND;
}
else if (i == JavaElementType.CONDITIONAL_EXPRESSION) {
int role = ((CompositeElement)oldParent).getChildRole(oldExpr);
if (role == ChildRole.THEN_EXPRESSION) return false;
return priority < parentPriority || role != ChildRole.ELSE_EXPRESSION;
}
else if (i == JavaElementType.BINARY_EXPRESSION || i == JavaElementType.POLYADIC_EXPRESSION) {
if (priority < parentPriority) return true;
PsiElement element = SourceTreeToPsiMap.treeElementToPsi(oldParent);
IElementType opType = ((PsiPolyadicExpression)element).getOperationTokenType();
return ((CompositeElement)oldParent).getChildRole(oldExpr) != ChildRole.LOPERAND &&
opType != JavaTokenType.PLUS &&
opType != JavaTokenType.ASTERISK &&
opType != JavaTokenType.ANDAND &&
opType != JavaTokenType.OROR;
}
else if (i == JavaElementType.INSTANCE_OF_EXPRESSION) {
return priority < parentPriority;
}
else if (i == JavaElementType.PREFIX_EXPRESSION || i == JavaElementType.TYPE_CAST_EXPRESSION) {
return priority < parentPriority;
}
else if (i == JavaElementType.POSTFIX_EXPRESSION) {
return priority <= parentPriority;
}
else if (i == JavaElementType.REFERENCE_EXPRESSION) {
return priority < parentPriority;
}
else if (i == JavaElementType.METHOD_CALL_EXPRESSION) {
return false;
}
else if (i == JavaElementType.NEW_EXPRESSION) {
return false;
}
else if (i == JavaElementType.ARRAY_ACCESS_EXPRESSION) {
int role = ((CompositeElement)oldParent).getChildRole(oldExpr);
return role != ChildRole.ARRAY_DIMENSION && priority < parentPriority;
}
else if (i == JavaElementType.ARRAY_INITIALIZER_EXPRESSION) {
return false;
}
else if (i == JavaElementType.PARENTH_EXPRESSION) {
return false;
}
else if (i == JavaElementType.LITERAL_EXPRESSION ||
i == JavaElementType.THIS_EXPRESSION ||
i == JavaElementType.SUPER_EXPRESSION ||
i == JavaElementType.CLASS_OBJECT_ACCESS_EXPRESSION ||
i == JavaElementType.LAMBDA_EXPRESSION ||
i == JavaElementType.METHOD_REF_EXPRESSION ) {
return false;
}
LOG.assertTrue(false);
return false;
}
private static int getExpressionPriority(ASTNode expr) {
IElementType i = expr.getElementType();
if (i == JavaElementType.ASSIGNMENT_EXPRESSION) {
return 0;
}
else if (i == JavaElementType.CONDITIONAL_EXPRESSION) {
return 1;
}
else if (i == JavaElementType.BINARY_EXPRESSION || i == JavaElementType.POLYADIC_EXPRESSION) {
PsiElement element = SourceTreeToPsiMap.treeElementToPsi(expr);
IElementType opType = ((PsiPolyadicExpression)element).getOperationTokenType();
if (opType == JavaTokenType.OROR) {
return 2;
}
else if (opType == JavaTokenType.ANDAND) {
return 3;
}
else if (opType == JavaTokenType.OR) {
return 4;
}
else if (opType == JavaTokenType.XOR) {
return 5;
}
else if (opType == JavaTokenType.AND) {
return 6;
}
else if (opType == JavaTokenType.EQEQ || opType == JavaTokenType.NE) {
return 7;
}
else if (opType == JavaTokenType.LT || opType == JavaTokenType.GT || opType == JavaTokenType.LE || opType == JavaTokenType.GE) {
return 8;
}
else if (opType == JavaTokenType.LTLT || opType == JavaTokenType.GTGT || opType == JavaTokenType.GTGTGT) {
return 9;
}
else if (opType == JavaTokenType.PLUS || opType == JavaTokenType.MINUS) {
return 10;
}
else if (opType == JavaTokenType.ASTERISK || opType == JavaTokenType.DIV || opType == JavaTokenType.PERC) {
return 11;
}
return 8;
}
else if (i == JavaElementType.INSTANCE_OF_EXPRESSION) {
return 8;
}
else if (i == JavaElementType.PREFIX_EXPRESSION || i == JavaElementType.TYPE_CAST_EXPRESSION) {
return 12;
}
else if (i == JavaElementType.POSTFIX_EXPRESSION) {
return 13;
}
else if (i == JavaElementType.LITERAL_EXPRESSION ||
i == JavaElementType.REFERENCE_EXPRESSION ||
i == JavaElementType.THIS_EXPRESSION ||
i == JavaElementType.SUPER_EXPRESSION ||
i == JavaElementType.PARENTH_EXPRESSION ||
i == JavaElementType.METHOD_CALL_EXPRESSION ||
i == JavaElementType.CLASS_OBJECT_ACCESS_EXPRESSION ||
i == JavaElementType.NEW_EXPRESSION ||
i == JavaElementType.ARRAY_ACCESS_EXPRESSION ||
i == JavaElementType.ARRAY_INITIALIZER_EXPRESSION ||
i == JavaElementType.JAVA_CODE_REFERENCE ||
i == JavaElementType.METHOD_REF_EXPRESSION ||
i == JavaElementType.LAMBDA_EXPRESSION ||
i == JavaElementType.EMPTY_EXPRESSION) {
return 14;
}
else {
LOG.error("Unknown element type:" + i);
return -1;
}
}
}