blob: 70c97495995bb9af9d5c79a197c4c4c829087d40 [file] [log] [blame]
/*
* Copyright 2000-2014 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.util;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.IncorrectOperationException;
import java.util.List;
import static com.intellij.psi.CommonClassNames.JAVA_LANG_STRING;
/**
* User: cdr
*/
public class PsiConcatenationUtil {
public static void buildFormatString(PsiExpression expression, StringBuilder formatString,
List<PsiExpression> formatParameters, boolean printfFormat) {
if (expression instanceof PsiLiteralExpression) {
final PsiLiteralExpression literalExpression = (PsiLiteralExpression) expression;
final String text = String.valueOf(literalExpression.getValue());
final String formatText;
if (printfFormat) {
formatText = StringUtil.escapeStringCharacters(text).replace("%", "%%").replace("\\'", "'");
}
else {
formatText = StringUtil.escapeStringCharacters(text).replace("'", "''").replaceAll("((\\{|})+)", "'$1'");
}
formatString.append(formatText);
} else if (expression instanceof PsiPolyadicExpression) {
final PsiType type = expression.getType();
if (type != null && type.equalsToText(JAVA_LANG_STRING)) {
final PsiPolyadicExpression binaryExpression = (PsiPolyadicExpression) expression;
PsiExpression[] operands = binaryExpression.getOperands();
PsiType left = operands[0].getType();
boolean stringStarted = left != null && left.equalsToText(JAVA_LANG_STRING);
if (stringStarted) {
buildFormatString(operands[0], formatString, formatParameters, printfFormat);
}
for (int i = 1; i < operands.length; i++) {
PsiExpression op = operands[i];
PsiType optype = op.getType();
PsiType r = TypeConversionUtil.calcTypeForBinaryExpression(left, optype, binaryExpression.getOperationTokenType(), true);
if (r != null && r.equalsToText(JAVA_LANG_STRING) && !stringStarted) {
stringStarted = true;
PsiElement element = binaryExpression.getTokenBeforeOperand(op);
if (element.getPrevSibling() instanceof PsiWhiteSpace) element = element.getPrevSibling();
String text = binaryExpression.getText().substring(0, element.getStartOffsetInParent());
PsiExpression subExpression = JavaPsiFacade.getInstance(binaryExpression.getProject()).getElementFactory()
.createExpressionFromText(text, binaryExpression);
addFormatParameter(subExpression, formatString, formatParameters, printfFormat);
}
if (stringStarted) {
if (optype != null && (optype.equalsToText(JAVA_LANG_STRING) || optype == PsiType.CHAR)) {
buildFormatString(op, formatString, formatParameters, printfFormat);
}
else {
addFormatParameter(op, formatString, formatParameters, printfFormat);
}
}
left = r;
}
}
else {
addFormatParameter(expression, formatString, formatParameters, printfFormat);
}
}
else {
addFormatParameter(expression, formatString, formatParameters, printfFormat);
}
}
private static void addFormatParameter(PsiExpression expression,
StringBuilder formatString,
List<PsiExpression> formatParameters, boolean printfFormat) {
final PsiType type = expression.getType();
if (!printfFormat) {
formatString.append("{").append(formatParameters.size()).append("}");
}
else if (type != null &&
(type.equalsToText("long") ||
type.equalsToText("int") ||
type.equalsToText("java.lang.Long") ||
type.equalsToText("java.lang.Integer"))) {
formatString.append("%d");
}
else {
formatString.append("%s");
}
formatParameters.add(getBoxedArgument(expression));
}
private static PsiExpression getBoxedArgument(PsiExpression arg) throws IncorrectOperationException {
arg = PsiUtil.deparenthesizeExpression(arg);
assert arg != null;
if (PsiUtil.isLanguageLevel5OrHigher(arg)) {
return arg;
}
final PsiType type = arg.getType();
if (!(type instanceof PsiPrimitiveType) || type.equals(PsiType.NULL)) {
return arg;
}
final PsiPrimitiveType primitiveType = (PsiPrimitiveType)type;
final String boxedQName = primitiveType.getBoxedTypeName();
if (boxedQName == null) {
return arg;
}
final GlobalSearchScope resolveScope = arg.getResolveScope();
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(arg.getProject());
final PsiJavaCodeReferenceElement ref = factory.createReferenceElementByFQClassName(boxedQName, resolveScope);
final PsiNewExpression newExpr = (PsiNewExpression)factory.createExpressionFromText("new A(b)", null);
final PsiElement classRef = newExpr.getClassReference();
assert classRef != null;
classRef.replace(ref);
final PsiExpressionList argumentList = newExpr.getArgumentList();
assert argumentList != null;
argumentList.getExpressions()[0].replace(arg);
return newExpr;
}
}