FoldExpressionIntoStream: disable for non-string separator and automatically convert char

CharToStringIntention#stringForCharLiteral moved to PsiLiteralUtil
Fixes IDEA-195621 "Expression can be folded into Stream chain" produces red code when delimiter is char type
This commit is contained in:
Tagir Valeev
2018-07-29 13:41:30 +07:00
parent 0ee4ea1fad
commit 229f9206e8
6 changed files with 62 additions and 15 deletions
@@ -11,6 +11,7 @@ import com.intellij.psi.codeStyle.VariableKind;
import com.intellij.psi.impl.PsiDiamondTypeUtil;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiLiteralUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.ArrayUtil;
@@ -151,6 +152,10 @@ public class FoldExpressionIntoStreamInspection extends AbstractBaseJavaLocalIns
.pairMap(EquivalenceChecker.getCanonicalPsiEquivalence()::expressionsAreEquivalent)
.allMatch(Boolean.TRUE::equals)) {
delimiter = operands[1];
if (!InheritanceUtil.isInheritor(delimiter.getType(), "java.lang.CharSequence") &&
!(delimiter instanceof PsiLiteralExpression && PsiType.CHAR.equals(delimiter.getType()))) {
return null;
}
if (operands.length % 2 == 0) {
rest = ArrayUtil.getLastElement(operands);
}
@@ -272,8 +277,20 @@ public class FoldExpressionIntoStreamInspection extends AbstractBaseJavaLocalIns
String map = (lambda == null ? "" : mapToString(elementType, myOperandType, lambda)) + myMapToString;
return map +
".collect(" + CommonClassNames.JAVA_UTIL_STREAM_COLLECTORS +
".joining(" + (myDelimiter == null ? "" : ct.text(myDelimiter)) + "))" +
".joining(" + getDelimiterText(ct) + "))" +
(myRest == null ? "" : "+" + ct.text(myRest));
}
@NotNull
private String getDelimiterText(CommentTracker ct) {
if (myDelimiter == null) {
return "";
}
String text = ct.text(myDelimiter);
if (text.startsWith("'")) {
return PsiLiteralUtil.stringForCharLiteral(text);
}
return text;
}
}
}
@@ -3,6 +3,7 @@ package com.intellij.psi.util;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class PsiLiteralUtil {
@@ -103,4 +104,24 @@ public class PsiLiteralUtil {
integer |= lastDigit;
return integer;
}
/**
* Converts passed character literal (like 'a') to string literal (like "a").
*
* @param charLiteral character literal to convert.
* @return resulting string literal
*/
@NotNull
public static String stringForCharLiteral(@NotNull String charLiteral) {
if ("'\"'".equals(charLiteral)) {
return "\"\\\"\"";
}
else if ("'\\''".equals(charLiteral)) {
return "\"'\"";
}
else {
return '\"' + charLiteral.substring(1, charLiteral.length() - 1) +
'\"';
}
}
}
@@ -0,0 +1,7 @@
// "Fold expression into 'String.join'" "true"
class Test {
String foo(String a, String b, String c) {
String s = String.join("_", a, b, c);
return s;
}
}
@@ -0,0 +1,7 @@
// "Fold expression into 'String.join'" "true"
class Test {
String foo(String a, String b, String c) {
String s = a + <caret>'_' + b + '_' + c ;
return s;
}
}
@@ -0,0 +1,7 @@
// "Fold expression into 'String.join'" "false"
class Test {
String foo(String a, String b, String c) {
String s = a + <caret>5 + b + 5 + c ;
return s;
}
}
@@ -17,6 +17,7 @@ package com.siyeh.ipp.chartostring;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiLiteralExpression;
import com.intellij.psi.util.PsiLiteralUtil;
import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ipp.base.Intention;
import com.siyeh.ipp.base.PsiElementPredicate;
@@ -34,20 +35,7 @@ public class CharToStringIntention extends Intention {
public void processIntention(@NotNull PsiElement element) {
final PsiLiteralExpression charLiteral = (PsiLiteralExpression)element;
final String charLiteralText = charLiteral.getText();
final String stringLiteral = stringForCharLiteral(charLiteralText);
final String stringLiteral = PsiLiteralUtil.stringForCharLiteral(charLiteralText);
PsiReplacementUtil.replaceExpression(charLiteral, stringLiteral);
}
private static String stringForCharLiteral(String charLiteral) {
if ("'\"'".equals(charLiteral)) {
return "\"\\\"\"";
}
else if ("'\\''".equals(charLiteral)) {
return "\"'\"";
}
else {
return '\"' + charLiteral.substring(1, charLiteral.length() - 1) +
'\"';
}
}
}