Java: quick-fix should not make code uncompilable (IDEA-290348)

for "Method parameter always has the same value" inspection

GitOrigin-RevId: 114ab7d07d50298101555f3203b5161deea17816
This commit is contained in:
Bas Leijdekkers
2023-05-12 00:51:56 +00:00
committed by intellij-monorepo-bot
parent 323a96b4ee
commit 3944be5659
9 changed files with 112 additions and 30 deletions
@@ -20,8 +20,8 @@ import java.util.Objects;
import java.util.function.Supplier;
public class RefParameterImpl extends RefJavaElementImpl implements RefParameter {
private static final int USED_FOR_READING_MASK = 0b1_00000000_00000000;
private static final int USED_FOR_WRITING_MASK = 0b10_00000000_00000000;
private static final int USED_FOR_READING_MASK = 0b01_00000000_00000000; // 17th bit
private static final int USED_FOR_WRITING_MASK = 0b10_00000000_00000000; // 18th bit
private final short myIndex;
private Object myActualValueTemplate; // guarded by this
@@ -185,10 +185,32 @@ public class RefParameterImpl extends RefJavaElementImpl implements RefParameter
}
//don't unescape/escape to insert into the source file
PsiElement sourcePsi = Objects.requireNonNull(expression.getSourcePsi());
return value instanceof String ? ("\"" + StringUtil.unquoteString(sourcePsi.getText()) + "\"") : value;
return value instanceof String
? ("\"" + StringUtil.unquoteString(sourcePsi.getText()) + "\"")
: convertToStringRepresentation(value);
}
Object constValue = expression.evaluate(); //JavaConstantExpressionEvaluator.computeConstantExpression(expression, false);
return constValue == null ? VALUE_IS_NOT_CONST : constValue instanceof String ? "\"" + constValue + "\"" : constValue;
Object value = expression.evaluate();
return value == null ? VALUE_IS_NOT_CONST : convertToStringRepresentation(value);
}
@Nullable
private static Object convertToStringRepresentation(Object value) {
if (value instanceof Long) {
return value + "L";
}
else if (value instanceof Short) {
return "(short)" + value;
}
else if (value instanceof Byte) {
return "(byte)" + value;
}
else if (value instanceof String string) {
return "\"" + StringUtil.escapeStringCharacters(string) + "\"";
}
else if (value instanceof Character character) {
return "'" + StringUtil.escapeCharCharacters(String.valueOf(character)) + "'";
}
return value;
}
private static boolean isAccessible(@NotNull UField field, @NotNull PsiElement place) {
@@ -175,37 +175,31 @@ public class SameParameterValueInspection extends GlobalJavaBatchInspectionTool
boolean suggestFix) {
final String name = parameter.getName();
if (name == null || name.isEmpty()) return null;
String shortName;
String stringPresentation;
String presentableText;
String canonicalText;
if (value instanceof PsiType) {
stringPresentation = ((PsiType)value).getCanonicalText() + ".class";
shortName = ((PsiType)value).getPresentableText() + ".class";
canonicalText = ((PsiType)value).getCanonicalText() + ".class";
presentableText = ((PsiType)value).getPresentableText() + ".class";
}
else {
if (value instanceof PsiField) {
stringPresentation = PsiFormatUtil.formatVariable((PsiVariable)value,
PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_CONTAINING_CLASS | PsiFormatUtilBase.SHOW_FQ_NAME,
PsiSubstitutor.EMPTY);
shortName = PsiFormatUtil.formatVariable((PsiVariable)value,
PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_CONTAINING_CLASS,
PsiSubstitutor.EMPTY);
}
else if (value instanceof Character) {
stringPresentation = shortName = "'" + value + "'";
canonicalText = PsiFormatUtil.formatVariable((PsiVariable)value,
PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_CONTAINING_CLASS | PsiFormatUtilBase.SHOW_FQ_NAME,
PsiSubstitutor.EMPTY);
presentableText = PsiFormatUtil.formatVariable((PsiVariable)value,
PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_CONTAINING_CLASS,
PsiSubstitutor.EMPTY);
}
else {
stringPresentation = shortName = String.valueOf(value);
canonicalText = presentableText = String.valueOf(value);
}
}
PsiElement anchor = ObjectUtils.notNull(UDeclarationKt.getAnchorPsi(parameter), parameter);
if (!anchor.isPhysical()) return null;
String value1 = stringPresentation.startsWith("\"\"")
? stringPresentation
: StringUtil.escapeLineBreak(stringPresentation);
return manager.createProblemDescriptor(anchor,
JavaBundle.message("inspection.same.parameter.problem.descriptor",
StringUtil.unquoteString(shortName)),
suggestFix ? new InlineParameterValueFix(name, value1) : null,
StringUtil.unquoteString(presentableText)),
suggestFix ? new InlineParameterValueFix(name, canonicalText) : null,
ProblemHighlightType.GENERIC_ERROR_OR_WARNING, false);
}
@@ -0,0 +1,12 @@
class SampleClazz {
private void handleTree() {
foo((short) 0);
}
void foo(short sss){}
public static void main(String[] args) {
new SampleClazz().handleTree();
}
}
@@ -0,0 +1,12 @@
class SampleClazz {
private void handleTree(Short <warning descr="Actual value of parameter 'simflag' is always '(short)0'"><caret>simflag</warning>) {
foo(simflag);
}
void foo(short sss){}
public static void main(String[] args) {
new SampleClazz().handleTree((short) 0);
}
}
@@ -0,0 +1,10 @@
class LongValue {
void x() {
System.out.println(10000000000L);
}
void y() {
x();
}
}
@@ -0,0 +1,10 @@
class LongValue {
void x(long <warning descr="Actual value of parameter 'l' is always '10000000000L'"><caret>l</warning>) {
System.out.println(l);
}
void y() {
x(10000000000L);
}
}
@@ -0,0 +1,10 @@
class StringThatNeedsEscaping {
void x() {
System.out.println("quote\"");
}
void y() {
x();
}
}
@@ -0,0 +1,10 @@
class StringThatNeedsEscaping {
void x(String <caret>s) {
System.out.println(s);
}
void y() {
x("quote" + "\"");
}
}
@@ -15,19 +15,21 @@ import java.util.List;
*/
public final class SameParameterValueQuickFixTest extends LightJavaCodeInsightFixtureTestCase {
public void testSimple() {
doTest();
}
public void testSimple() { doTest(); }
public void testCastedValue() { doTest(); }
public void testStringThatNeedsEscaping() { doTest(false); }
public void testLongValue() { doTest(); }
private void doTest() {
doNamedTest(getTestName(false));
doTest(true);
}
private void doNamedTest(String name) {
private void doTest(boolean testHighlighting) {
String name = getTestName(false);
LocalInspectionTool inspection = new SameParameterValueInspection().getSharedLocalInspectionTool();
myFixture.enableInspections(inspection);
myFixture.configureByFile(name + ".java");
myFixture.testHighlighting(true, false, false);
if (testHighlighting) myFixture.testHighlighting(true, false, false);
final @NotNull List<IntentionAction> intentions = myFixture.filterAvailableIntentions("Inline value");
assertEquals("intention not found", 1, intentions.size());
myFixture.checkPreviewAndLaunchAction(intentions.get(0));