From cc9c5fe1079af28ddf08c24edc8e3c05e620bbaf Mon Sep 17 00:00:00 2001 From: "Andrey.Cherkasov" Date: Wed, 6 Oct 2021 06:04:17 +0300 Subject: [PATCH] [java-highlighting] Provide fixes for unexpected primitive type pattern IDEA-279711 GitOrigin-RevId: 58d634c764bf9ab92d0821d3e456ab4e267b2eb9 --- .../intention/QuickFixFactory.java | 2 ++ .../SwitchBlockHighlightingModel.java | 24 +++++++++++++++++-- .../daemon/impl/quickfix/VariableTypeFix.java | 2 +- .../impl/config/QuickFixFactoryImpl.java | 5 ++++ .../variableType/afterPatternVariable1.java | 8 +++++++ .../variableType/afterPatternVariable2.java | 8 +++++++ .../variableType/beforePatternVariable1.java | 8 +++++++ .../variableType/beforePatternVariable2.java | 8 +++++++ .../daemon/quickFix/VariableTypeTest.java | 8 +++++++ 9 files changed, 70 insertions(+), 3 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/variableType/afterPatternVariable1.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/variableType/afterPatternVariable2.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/variableType/beforePatternVariable1.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/variableType/beforePatternVariable2.java diff --git a/java/java-analysis-api/src/com/intellij/codeInsight/intention/QuickFixFactory.java b/java/java-analysis-api/src/com/intellij/codeInsight/intention/QuickFixFactory.java index c3b099d6da49..0420caeffed6 100644 --- a/java/java-analysis-api/src/com/intellij/codeInsight/intention/QuickFixFactory.java +++ b/java/java-analysis-api/src/com/intellij/codeInsight/intention/QuickFixFactory.java @@ -529,6 +529,8 @@ public abstract class QuickFixFactory { public abstract @NotNull IntentionAction createReceiverParameterTypeFix(@NotNull PsiReceiverParameter receiverParameter, @NotNull PsiType enclosingClassType); + public abstract @NotNull IntentionAction createVariableTypeFix(@NotNull PsiVariable variable, @NotNull PsiType type); + public abstract @NotNull IntentionAction createConvertInterfaceToClassFix(@NotNull PsiClass aClass); @Nullable diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/SwitchBlockHighlightingModel.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/SwitchBlockHighlightingModel.java index bbd593117662..10e807879aa8 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/SwitchBlockHighlightingModel.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/SwitchBlockHighlightingModel.java @@ -443,10 +443,16 @@ public class SwitchBlockHighlightingModel { return null; } else if (label instanceof PsiPattern) { - PsiType patternType = JavaPsiPatternUtil.getPatternType((PsiPattern)label); + PsiPattern pattern = (PsiPattern)label; + PsiType patternType = JavaPsiPatternUtil.getPatternType(pattern); if (!(patternType instanceof PsiClassType) && !(patternType instanceof PsiArrayType)) { String expectedTypes = JavaErrorBundle.message("switch.class.or.array.type.expected"); - return createError(label, JavaErrorBundle.message("unexpected.type", expectedTypes, JavaHighlightUtil.formatType(patternType))); + String message = JavaErrorBundle.message("unexpected.type", expectedTypes, JavaHighlightUtil.formatType(patternType)); + HighlightInfo info = createError(label, message); + if (patternType instanceof PsiPrimitiveType) { + registerVariableTypeFixes(info, pattern, (PsiPrimitiveType)patternType); + } + return info; } if (!TypeConversionUtil.areTypesConvertible(mySelectorType, patternType)) { return HighlightUtil.createIncompatibleTypeHighlightInfo(mySelectorType, patternType, label.getTextRange(), 0); @@ -740,6 +746,20 @@ public class SwitchBlockHighlightingModel { QuickFixAction.registerQuickFixAction(info, getFixFactory().createDeleteDefaultFix(myFile, info)); } + private static void registerVariableTypeFixes(@Nullable HighlightInfo info, + @NotNull PsiPattern pattern, + @NotNull PsiPrimitiveType primitiveType) { + PsiType arrayType = PsiTypesUtil.createArrayType(primitiveType, 1); + PsiPatternVariable patternVariable = JavaPsiPatternUtil.getPatternVariable(pattern); + if (patternVariable == null) return; + PsiClassType boxedType = primitiveType.getBoxedType(patternVariable); + IntentionAction changeToArrayTypeFix = getFixFactory().createVariableTypeFix(patternVariable, arrayType); + QuickFixAction.registerQuickFixAction(info, changeToArrayTypeFix); + if (boxedType == null) return; + IntentionAction changeToBoxTypeFix = getFixFactory().createVariableTypeFix(patternVariable, boxedType); + QuickFixAction.registerQuickFixAction(info, changeToBoxTypeFix); + } + private void checkSealedClassCompleteness(@NotNull PsiClass selectorClass, @NotNull List elements, @NotNull List results) { diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableTypeFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableTypeFix.java index c0748711f53f..6beb81e06366 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableTypeFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableTypeFix.java @@ -34,7 +34,7 @@ public class VariableTypeFix extends LocalQuickFixAndIntentionActionOnPsiElement private final PsiType myReturnType; protected final String myName; - protected VariableTypeFix(@NotNull PsiVariable variable, @NotNull PsiType toReturn) { + public VariableTypeFix(@NotNull PsiVariable variable, @NotNull PsiType toReturn) { super(variable); myReturnType = GenericsUtil.getVariableTypeByExpressionType(toReturn); myName = variable.getName(); diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/config/QuickFixFactoryImpl.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/config/QuickFixFactoryImpl.java index 2b443d188553..5fb933a03261 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/config/QuickFixFactoryImpl.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/config/QuickFixFactoryImpl.java @@ -1052,6 +1052,11 @@ public final class QuickFixFactoryImpl extends QuickFixFactory { }; } + @Override + public @NotNull IntentionAction createVariableTypeFix(@NotNull PsiVariable variable, @NotNull PsiType type) { + return new VariableTypeFix(variable, type); + } + @Override public @NotNull IntentionAction createConvertInterfaceToClassFix(@NotNull PsiClass aClass) { return new ConvertInterfaceToClassFix(aClass); diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/variableType/afterPatternVariable1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/variableType/afterPatternVariable1.java new file mode 100644 index 000000000000..3b98bf20b1b6 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/variableType/afterPatternVariable1.java @@ -0,0 +1,8 @@ +// "Change variable 'i' type to 'Integer'" "true" +class Test { + void foo(Object o) { + switch (o) { + case Integer i -> System.out.println("int"); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/variableType/afterPatternVariable2.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/variableType/afterPatternVariable2.java new file mode 100644 index 000000000000..3c344f691e10 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/variableType/afterPatternVariable2.java @@ -0,0 +1,8 @@ +// "Change variable 'i' type to 'int[]'" "true" +class Test { + void foo(Object o) { + switch (o) { + case int[] i -> System.out.println("int"); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/variableType/beforePatternVariable1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/variableType/beforePatternVariable1.java new file mode 100644 index 000000000000..b25b2d998ea9 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/variableType/beforePatternVariable1.java @@ -0,0 +1,8 @@ +// "Change variable 'i' type to 'Integer'" "true" +class Test { + void foo(Object o) { + switch (o) { + case int i -> System.out.println("int"); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/variableType/beforePatternVariable2.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/variableType/beforePatternVariable2.java new file mode 100644 index 000000000000..04eb7ab0fafc --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/variableType/beforePatternVariable2.java @@ -0,0 +1,8 @@ +// "Change variable 'i' type to 'int[]'" "true" +class Test { + void foo(Object o) { + switch (o) { + case int i -> System.out.println("int"); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/quickFix/VariableTypeTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/quickFix/VariableTypeTest.java index 5744bfb14566..26a689978957 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/quickFix/VariableTypeTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/quickFix/VariableTypeTest.java @@ -2,11 +2,19 @@ package com.intellij.java.codeInsight.daemon.quickFix; import com.intellij.codeInsight.daemon.quickFix.LightQuickFixParameterizedTestCase; +import com.intellij.testFramework.LightProjectDescriptor; +import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase; +import org.jetbrains.annotations.NotNull; public class VariableTypeTest extends LightQuickFixParameterizedTestCase { @Override protected String getBasePath() { return "/codeInsight/daemonCodeAnalyzer/quickFix/variableType"; } + + @Override + protected @NotNull LightProjectDescriptor getProjectDescriptor() { + return LightJavaCodeInsightFixtureTestCase.JAVA_17; + } }