[codeInsight] IDEA-240288 Inspection for StringBuilder.toString().substring()

This patch alters the `getRedundantStringBuilderToStringProblem` method with more sophisticated algorithm to detect unnecessary freestanding `StringBuilder#toString` calls. If the call is a part of a polyadic expression it checks if there is at least one string operand (either a constant literal or a local variable or a constant variable or a method call) and based on that information it detects redundant `StringBuilder#toString` calls.

Signed-off-by: Nikita Eshkeev <nikita.eshkeev@jetbrains.com>

GitOrigin-RevId: e09ea8b8829ad9e28e8ff1bcfad34cf6b191aa6b
This commit is contained in:
Nikita Eshkeev
2020-05-12 00:59:21 +00:00
committed by intellij-monorepo-bot
parent 264b599e59
commit cb47b00f60
7 changed files with 354 additions and 79 deletions
@@ -1,7 +1,11 @@
// "Fix all 'Redundant String operation' problems in file" "true"
class StringBuilderToString {
StringBuilderToString() {
private static final String CONST_STRING_VAL = "Hello";
static String str() { return ""; }
void stringBuilderToStringSubstring() {
String s1 = new StringBuilder().toString();
/* 1 */
String s2 = new StringBuilder()/* 2 */.substring(1);
@@ -22,35 +26,8 @@ class StringBuilderToString {
System.out.println(new StringBuilder()/* 2 */.substring(1, 3).length());
System.out.println(new StringBuilder().substring(1, 3));
System.out.println(new StringBuilder().substring(1, 3).length());
StringBuilder sb = new StringBuilder();
/* 1 */
String s6 = sb/* 2 */ + sb. /* 3 */toString()/* 4 */;
/* 1 */
String s7 = sb/* 2 */ + sb./* 3 */toString()/* 4 */;
String s8 = "Hello, World" + sb.toString();
String s8 = ("Hello, " + "World") + sb.toString();
String s9 = sb./* 1 */toString()/* 2 */ + 42;
/* 1 */
String s10 = sb/* 2 */ + "Hello, World";
/* 3 */
/* 1 */
String s11 = sb/* 2 */ + sb/* 4 */ + sb./* 5 */toString()/* 6 */;
/* 1 */
System.out.println(sb/* 2 */ + sb. /* 3 */toString()/* 4 */);
/* 1 */
System.out.println(sb/* 2 */ + sb./* 3 */toString()/* 4 */);
/* 3 */
/* 1 */
System.out.println(sb/* 2 */ + sb/* 4 */ + sb./* 5 */toString()/* 6 */);
System.out.println("Hello, World" + sb.toString());
System.out.println(("Hello, " + "World") + sb.toString());
System.out.println(sb./* 1 */toString()/* 2 */ + 42);
/* 1 */
System.out.println(sb/* 2 */ + "Hello, World");
}
void builder(StringBuilder sb) {
String s1 = sb.toString();
/* 1 */
@@ -62,11 +39,6 @@ class StringBuilderToString {
/* 1 */
int s5 = sb/* 2 */.substring(1, 4).length();
/* 1 */
String s6 = sb.append(sb)/* 2 */.substring(1);
/* 1 */
String s7 = (sb/* 2 */ + sb./* 3 */toString()/* 4 */).substring(1);
/* 1 */
System.out.println(sb/* 2 */);
/* 1 */
@@ -77,10 +49,5 @@ class StringBuilderToString {
System.out.println(sb/* 2 */.substring(1, 3).length());
System.out.println(sb.substring(1, 3));
System.out.println(sb.substring(1, 3).length());
f(sb);
f(sb.toString());
}
void f(StringBuilder s) {}
void f(String s) {}
}
@@ -0,0 +1,88 @@
// "Fix all 'Redundant String operation' problems in file" "true"
class StringBuilderToStringArgs {
private static final String CONST_STRING_VAL = "Hello";
static String str() { return ""; }
static void stringBuilderToStringArgs(StringBuilder sb) {
/* 2 */
/* 3 */
/* 4 */
System.out.println(/* 1 */sb/* 5 */ + "Hello");
/* 2 */
/* 3 */
/* 4 */
System.out.println("Hello" + /* 1 */sb/* 5 */);
System.out.println(/* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */ + 42);
/* 2 */
/* 3 */
/* 4 */
System.out.println("Hello" + /* 1 */sb/* 5 */ + 42);
final String finalVal = "Hello";
/* 2 */
/* 3 */
/* 4 */
System.out.println(/* 1 */sb/* 5 */ + finalVal);
/* 2 */
/* 3 */
/* 4 */
System.out.println(finalVal + /* 1 */sb/* 5 */);
/* 2 */
/* 3 */
/* 4 */
System.out.println(finalVal + /* 1 */sb/* 5 */ + 42);
String stringVal = "Hello";
/* 2 */
/* 3 */
/* 4 */
System.out.println(stringVal + /* 1 */sb/* 5 */ + 42);
int intVal = 42;
System.out.println(intVal + /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */ + 42);
final int constIntVal = 42;
System.out.println(/* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */ + constIntVal);
System.out.println(constIntVal + /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */);
System.out.println(constIntVal + /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */ + 42);
/* 2 */
/* 3 */
/* 4 */
System.out.println(CONST_STRING_VAL + /* 1 */sb/* 5 */);
/* 2 */
/* 3 */
/* 4 */
System.out.println(/* 1 */sb/* 5 */ + CONST_STRING_VAL);
/* 2 */
/* 3 */
/* 4 */
System.out.println(CONST_STRING_VAL + /* 1 */sb/* 5 */ + 42);
/* 2 */
/* 3 */
/* 4 */
System.out.println(str() + /* 1 */sb/* 5 */);
/* 2 */
/* 3 */
/* 4 */
System.out.println(/* 1 */sb/* 5 */ + str());
/* 2 */
/* 3 */
/* 4 */
System.out.println(str() + /* 1 */sb/* 5 */ + str());
System.out.println(/* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */ + /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */);
System.out.println(/* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */ + /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */ + /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */);
System.out.println(("Hello" + sb) + sb + sb);
System.out.println(("Hello" + sb) + sb + sb);
System.out.println((("Hello" + sb) + sb) + sb);
System.out.println(("Hello" + sb + (sb.toString() + ((sb.toString())))));
System.out.println(("Hello" + sb + (sb + ((sb) + "Hello"))));
System.out.println(("Hello" + sb + (sb + ((sb.toString()) + 42))));
}
}
@@ -0,0 +1,89 @@
// "Fix all 'Redundant String operation' problems in file" "true"
class StringBuilderToStringAssign {
public static final String CONST_STRING_VAL = "Hello";
static String str() { return ""; }
static void stringBuilderToStringAssign(StringBuilder sb) {
String s1 = sb + "Hello";
/* 2 */
/* 3 */
/* 4 */
String s2 = "Hello" + /* 1 */sb/* 5 */;
String s3 = /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */ + 42;
/* 2 */
/* 3 */
/* 4 */
String s4 = "Hello" + /* 1 */sb/* 5 */ + 42;
final String finalVal = "Hello";
/* 2 */
/* 3 */
/* 4 */
String s5 = finalVal + /* 1 */sb/* 5 */ + 42;
String stringVal = "Hello";
/* 2 */
/* 3 */
/* 4 */
String s611 = /* 1 */sb/* 5 */ + stringVal;
/* 2 */
/* 3 */
/* 4 */
String s621 = stringVal + /* 1 */sb/* 5 */;
/* 2 */
/* 3 */
/* 4 */
String s631 = stringVal + /* 1 */sb/* 5 */ + 42;
int intVal = 42;
String s612 = /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */ + intVal;
String s622 = intVal + /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */;
String s632 = intVal + /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */ + 42;
final int constIntVal = 42;
String s61 = constIntVal + /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */;
String s62 = /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */ + constIntVal;
String s63 = /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */ + constIntVal + 42;
/* 2 */
/* 3 */
/* 4 */
String s71 = CONST_STRING_VAL + /* 1 */sb/* 5 */;
/* 2 */
/* 3 */
/* 4 */
String s72 = /* 1 */sb/* 5 */ + CONST_STRING_VAL;
/* 2 */
/* 3 */
/* 4 */
String s73 = CONST_STRING_VAL + /* 1 */sb/* 5 */ + 42;
/* 2 */
/* 3 */
/* 4 */
String s81 = str() + /* 1 */sb/* 5 */;
/* 2 */
/* 3 */
/* 4 */
String s82 = /* 1 */sb/* 5 */ + str();
/* 2 */
/* 3 */
/* 4 */
String s83 = str() + /* 1 */sb/* 5 */ + str();
String s91 = /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */ + /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */;
String s92 = /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */ + /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */ + /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */;
String s101 = ("Hello" + sb) + sb + sb;
String s102 = ("Hello" + sb) + sb + sb;
String s103 = (("Hello" + sb) + sb) + sb;
String s104 = ("Hello" + sb + (sb.toString() + ((sb.toString()))));
String s105 = ("Hello" + sb + (sb + ((sb) + "Hello")));
String s106 = ("Hello" + sb + (sb + ((sb.toString()) + 42)));
}
}
@@ -1,9 +1,13 @@
// "Fix all 'Redundant String operation' problems in file" "true"
class StringBuilderToString {
StringBuilderToString() {
private static final String CONST_STRING_VAL = "Hello";
static String str() { return ""; }
void stringBuilderToStringSubstring() {
String s1 = new StringBuilder().toString();
String s2 = new StringBuilder()./* 1 */<caret>toString()/* 2 */.substring(1);
String s2 = new StringBuilder()./* 1 */to<caret>String()/* 2 */.substring(1);
String s3 = new StringBuilder()./* 1 */toString()/* 2 */.substring(1, 4);
String s4 = new StringBuilder()./* 1 */toString()/* 2 */.substring(1, 4);
int s5 = new StringBuilder()./* 1 */toString()/* 2 */.substring(1, 4).length();
@@ -14,25 +18,8 @@ class StringBuilderToString {
System.out.println(new StringBuilder()./* 1 */toString()/* 2 */.substring(1, 3).length());
System.out.println(new StringBuilder().substring(1, 3));
System.out.println(new StringBuilder().substring(1, 3).length());
StringBuilder sb = new StringBuilder();
String s6 = sb./* 1 */toString()/* 2 */ + sb. /* 3 */toString()/* 4 */;
String s7 = sb./* 1 */toString()/* 2 */ + sb./* 3 */toString()/* 4 */;
String s8 = "Hello, World" + sb.toString();
String s8 = ("Hello, " + "World") + sb.toString();
String s9 = sb./* 1 */toString()/* 2 */ + 42;
String s10 = sb./* 1 */toString()/* 2 */ + "Hello, World";
String s11 = sb./* 1 */toString()/* 2 */ + sb./* 3 */toString()/* 4 */ + sb./* 5 */toString()/* 6 */;
System.out.println(sb./* 1 */toString()/* 2 */ + sb. /* 3 */toString()/* 4 */);
System.out.println(sb./* 1 */toString()/* 2 */ + sb./* 3 */toString()/* 4 */);
System.out.println(sb./* 1 */toString()/* 2 */ + sb./* 3 */toString()/* 4 */ + sb./* 5 */toString()/* 6 */);
System.out.println("Hello, World" + sb.toString());
System.out.println(("Hello, " + "World") + sb.toString());
System.out.println(sb./* 1 */toString()/* 2 */ + 42);
System.out.println(sb./* 1 */toString()/* 2 */ + "Hello, World");
}
void builder(StringBuilder sb) {
String s1 = sb.toString();
String s2 = sb./* 1 */toString()/* 2 */.substring(1);
@@ -40,19 +27,11 @@ class StringBuilderToString {
String s4 = sb./* 1 */toString()/* 2 */.substring(1, 4);
int s5 = sb./* 1 */toString()/* 2 */.substring(1, 4).length();
String s6 = sb.append(sb)./* 1 */toString()/* 2 */.substring(1);
String s7 = (sb./* 1 */toString()/* 2 */ + sb./* 3 */toString()/* 4 */).substring(1);
System.out.println(sb./* 1 */toString()/* 2 */);
System.out.println(sb./* 1 */toString()/* 2 */.substring(1));
System.out.println(sb./* 1 */toString()/* 2 */.substring(1, 3));
System.out.println(sb./* 1 */toString()/* 2 */.substring(1, 3).length());
System.out.println(sb.substring(1, 3));
System.out.println(sb.substring(1, 3).length());
f(sb);
f(sb.toString());
}
void f(StringBuilder s) {}
void f(String s) {}
}
@@ -0,0 +1,49 @@
// "Fix all 'Redundant String operation' problems in file" "true"
class StringBuilderToStringArgs {
private static final String CONST_STRING_VAL = "Hello";
static String str() { return ""; }
static void stringBuilderToStringArgs(StringBuilder sb) {
System.out.println(/* 1 */sb./* 2 */to<caret>String/* 3 */(/* 4 */)/* 5 */ + "Hello");
System.out.println("Hello" + /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */);
System.out.println(/* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */ + 42);
System.out.println("Hello" + /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */ + 42);
final String finalVal = "Hello";
System.out.println(/* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */ + finalVal);
System.out.println(finalVal + /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */);
System.out.println(finalVal + /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */ + 42);
String stringVal = "Hello";
System.out.println(stringVal + /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */ + 42);
int intVal = 42;
System.out.println(intVal + /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */ + 42);
final int constIntVal = 42;
System.out.println(/* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */ + constIntVal);
System.out.println(constIntVal + /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */);
System.out.println(constIntVal + /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */ + 42);
System.out.println(CONST_STRING_VAL + /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */);
System.out.println(/* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */ + CONST_STRING_VAL);
System.out.println(CONST_STRING_VAL + /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */ + 42);
System.out.println(str() + /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */);
System.out.println(/* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */ + str());
System.out.println(str() + /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */ + str());
System.out.println(/* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */ + /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */);
System.out.println(/* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */ + /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */ + /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */);
System.out.println(("Hello" + sb.toString()) + sb + sb.toString());
System.out.println(("Hello" + sb.toString()) + sb.toString() + sb.toString());
System.out.println((("Hello" + sb.toString()) + sb.toString()) + sb.toString());
System.out.println(("Hello" + sb.toString() + (sb.toString() + ((sb.toString())))));
System.out.println(("Hello" + sb.toString() + (sb.toString() + ((sb.toString()) + "Hello"))));
System.out.println(("Hello" + sb.toString() + (sb.toString() + ((sb.toString()) + 42))));
}
}
@@ -0,0 +1,53 @@
// "Fix all 'Redundant String operation' problems in file" "true"
class StringBuilderToStringAssign {
public static final String CONST_STRING_VAL = "Hello";
static String str() { return ""; }
static void stringBuilderToStringAssign(StringBuilder sb) {
String s1 = sb.<caret>toString() + "Hello";
String s2 = "Hello" + /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */;
String s3 = /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */ + 42;
String s4 = "Hello" + /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */ + 42;
final String finalVal = "Hello";
String s5 = finalVal + /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */ + 42;
String stringVal = "Hello";
String s611 = /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */ + stringVal;
String s621 = stringVal + /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */;
String s631 = stringVal + /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */ + 42;
int intVal = 42;
String s612 = /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */ + intVal;
String s622 = intVal + /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */;
String s632 = intVal + /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */ + 42;
final int constIntVal = 42;
String s61 = constIntVal + /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */;
String s62 = /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */ + constIntVal;
String s63 = /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */ + constIntVal + 42;
String s71 = CONST_STRING_VAL + /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */;
String s72 = /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */ + CONST_STRING_VAL;
String s73 = CONST_STRING_VAL + /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */ + 42;
String s81 = str() + /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */;
String s82 = /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */ + str();
String s83 = str() + /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */ + str();
String s91 = /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */ + /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */;
String s92 = /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */ + /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */ + /* 1 */sb./* 2 */toString/* 3 */(/* 4 */)/* 5 */;
String s101 = ("Hello" + sb.toString()) + sb + sb.toString();
String s102 = ("Hello" + sb.toString()) + sb.toString() + sb.toString();
String s103 = (("Hello" + sb.toString()) + sb.toString()) + sb.toString();
String s104 = ("Hello" + sb.toString() + (sb.toString() + ((sb.toString()))));
String s105 = ("Hello" + sb.toString() + (sb.toString() + ((sb.toString()) + "Hello")));
String s106 = ("Hello" + sb.toString() + (sb.toString() + ((sb.toString()) + 42)));
}
}
@@ -20,12 +20,10 @@ import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.callMatcher.CallMapper;
import com.siyeh.ig.callMatcher.CallMatcher;
import com.siyeh.ig.psiutils.*;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.PropertyKey;
import org.jetbrains.annotations.*;
import javax.swing.*;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
@@ -282,15 +280,17 @@ public class RedundantStringOperationInspection extends AbstractBaseJavaLocalIns
if (!ExpressionUtils.isConversionToStringNecessary(call, false)) {
// report naked `new StringBuilder().toString()`
final PsiElement parent = PsiUtil.skipParenthesizedExprUp(call.getParent());
if (parent instanceof PsiPolyadicExpression && ((PsiPolyadicExpression)parent).getOperationTokenType() == JavaTokenType.PLUS) {
// if there is a polyadic expression where all the operands are `new StringBuilder().toString()`
// then it is wrong to report all the `toString` calls as redundant: at least one of them should call
// `toString()`, let's choose the last one to remain with `toString()`
if (parent instanceof PsiPolyadicExpression) {
if (((PsiPolyadicExpression)parent).getOperationTokenType() != JavaTokenType.PLUS) return null;
final PsiPolyadicExpression polyadicExpression = (PsiPolyadicExpression)parent;
final PsiExpression lastChild = PsiUtil.skipParenthesizedExprDown(polyadicExpression.getOperands()[polyadicExpression.getOperands().length - 1]);
if (lastChild == call) {
return null;
}
final PsiExpression[] operands = polyadicExpression.getOperands();
final boolean hasStringOperand = Arrays.stream(operands)
.filter(operand -> operand != call)
.anyMatch(RedundantStringOperationVisitor::isOperandOfStringType);
if (!hasStringOperand) return null;
}
return getProblem(call, "inspection.redundant.string.call.message");
}
@@ -301,6 +301,56 @@ public class RedundantStringOperationInspection extends AbstractBaseJavaLocalIns
return getProblem(call, "inspection.redundant.string.call.message");
}
@Contract("null -> false")
private static boolean isOperandOfStringType(final PsiExpression op) {
final PsiExpression operand = PsiUtil.skipParenthesizedExprDown(op);
if (operand == null) return false;
if (operand instanceof PsiReferenceExpression) {
final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)operand;
final PsiElement resolve = referenceExpression.resolve();
final PsiType type;
if (resolve instanceof PsiVariable) {
type = ((PsiVariable)resolve).getType();
}
else if (resolve instanceof PsiMethod && ((PsiMethod)resolve).getReturnType() != null) {
type = ((PsiMethod)resolve).getReturnType();
}
else if (resolve instanceof PsiExpression && ((PsiExpression)resolve).getType() != null) {
type = ((PsiExpression)resolve).getType();
}
else {
return false;
}
if (type != null && type.equalsToText(String.class.getName())) {
return true;
}
}
else if (operand instanceof PsiMethodCallExpression) {
if (STRING_BUILDER_TO_STRING.matches(operand)) return false;
final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)operand;
final PsiMethod method = methodCallExpression.resolveMethod();
if (method != null && method.getReturnType() != null && method.getReturnType().equalsToText(String.class.getName())) {
return true;
}
}
else if (operand instanceof PsiPolyadicExpression) {
final PsiPolyadicExpression expression = (PsiPolyadicExpression)operand;
if (expression.getType() != null && expression.getType().equalsToText(String.class.getName())) {
return true;
}
}
else {
final String value = tryCast(ExpressionUtils.computeConstantExpression(operand), String.class);
if (value != null) {
return true;
}
}
return false;
}
@Nullable
private ProblemDescriptor getInternProblem(PsiMethodCallExpression call) {
return PsiUtil.isConstantExpression(call.getMethodExpression().getQualifierExpression())