From c78392d8020d5e16a939313e8b299f3da0269877 Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Fri, 11 Oct 2019 19:24:20 +0700 Subject: [PATCH] IDEA-177238 QuickFix for "Casting ... to ... may produce ClassCastException" GitOrigin-RevId: 000f7b616edb300b98cdefe04d954c5023365f8c --- .../guess/impl/GuessManagerImpl.java | 19 +------- .../dataFlow/DataFlowInspectionBase.java | 11 +++-- .../dataFlow/DataFlowInstructionVisitor.java | 13 +++++- .../codeInspection/dataFlow/DfaPsiUtil.java | 22 ++++++++++ .../codeInspection/ReplaceTypeInCastFix.java | 44 +++++++++++++++++++ .../dataFlow/DataFlowInspection.java | 33 +++++++++++--- .../replaceTypeInCast/afterAssignment.java | 9 ++++ .../replaceTypeInCast/afterInstanceOf.java | 10 +++++ .../replaceTypeInCast/afterIntersection.java | 10 +++++ .../replaceTypeInCast/beforeAssignment.java | 9 ++++ .../replaceTypeInCast/beforeInstanceOf.java | 10 +++++ .../replaceTypeInCast/beforeIntersection.java | 10 +++++ .../beforeNotInstanceOf.java | 10 +++++ .../quickFix/ReplaceTypeInCastFixTest.java | 43 ++++++++++++++++++ .../DataFlowInspectionTestSuite.java | 3 +- .../propertyBased/JavaIntentionPolicy.java | 1 + 16 files changed, 228 insertions(+), 29 deletions(-) create mode 100644 java/java-impl/src/com/intellij/codeInspection/ReplaceTypeInCastFix.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/replaceTypeInCast/afterAssignment.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/replaceTypeInCast/afterInstanceOf.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/replaceTypeInCast/afterIntersection.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/replaceTypeInCast/beforeAssignment.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/replaceTypeInCast/beforeInstanceOf.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/replaceTypeInCast/beforeIntersection.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/replaceTypeInCast/beforeNotInstanceOf.java create mode 100644 java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/quickFix/ReplaceTypeInCastFixTest.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/guess/impl/GuessManagerImpl.java b/java/java-analysis-impl/src/com/intellij/codeInsight/guess/impl/GuessManagerImpl.java index 0fd49d12b8f4..4d0307a26887 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/guess/impl/GuessManagerImpl.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/guess/impl/GuessManagerImpl.java @@ -344,7 +344,7 @@ public class GuessManagerImpl extends GuessManager { GuessTypeVisitor visitor = tryGuessingTypeWithoutDfa(place, honorAssignments); if (!visitor.isDfaNeeded()) { result = visitor.mySpecificType == null ? - Collections.emptyList() : Collections.singletonList(tryGenerify(expr, visitor.mySpecificType)); + Collections.emptyList() : Collections.singletonList(DfaPsiUtil.tryGenerify(expr, visitor.mySpecificType)); } } if (result == null) { @@ -386,26 +386,11 @@ public class GuessManagerImpl extends GuessManager { private static List flattenConjuncts(@NotNull PsiExpression expr, Collection conjuncts) { if (!conjuncts.isEmpty()) { Set flatTypes = PsiIntersectionType.flatten(conjuncts.toArray(PsiType.EMPTY_ARRAY), new LinkedHashSet<>()); - return ContainerUtil.mapNotNull(flatTypes, type -> tryGenerify(expr, type)); + return ContainerUtil.mapNotNull(flatTypes, type -> DfaPsiUtil.tryGenerify(expr, type)); } return Collections.emptyList(); } - private static PsiType tryGenerify(PsiExpression expression, PsiType type) { - if (!(type instanceof PsiClassType)) { - return type; - } - PsiClassType classType = (PsiClassType)type; - if (!classType.isRaw()) { - return classType; - } - PsiClass psiClass = classType.resolve(); - if (psiClass == null) return classType; - PsiType expressionType = expression.getType(); - if (!(expressionType instanceof PsiClassType)) return classType; - return GenericsUtil.getExpectedGenericType(expression, psiClass, (PsiClassType)expressionType); - } - private static class GuessTypeVisitor extends JavaElementVisitor { private static final CallMatcher OBJECT_GET_CLASS = CallMatcher.exactInstanceCall(CommonClassNames.JAVA_LANG_OBJECT, "getClass").parameterCount(0); diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java index 63fc64ee29f6..e6e7d530f2b0 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java @@ -235,7 +235,10 @@ public abstract class DataFlowInspectionBase extends AbstractBaseJavaLocalInspec } @NotNull - protected List createCastFixes(PsiTypeCastExpression castExpression, boolean onTheFly) { + protected List createCastFixes(PsiTypeCastExpression castExpression, + PsiType realType, + boolean onTheFly, + boolean alwaysFails) { return Collections.emptyList(); } @@ -713,13 +716,15 @@ public abstract class DataFlowInspectionBase extends AbstractBaseJavaLocalInspec } private void reportFailingCasts(ProblemReporter reporter, DataFlowInstructionVisitor visitor) { - visitor.getFailingCastExpressions().forKeyValue((typeCast, alwaysFails) -> { + visitor.getFailingCastExpressions().forKeyValue((typeCast, info) -> { + boolean alwaysFails = info.getFirst(); + PsiType realType = info.getSecond(); if (!REPORT_UNSOUND_WARNINGS && !alwaysFails) return; PsiExpression operand = typeCast.getOperand(); PsiTypeElement castType = typeCast.getCastType(); assert castType != null; assert operand != null; - List fixes = new ArrayList<>(createCastFixes(typeCast, reporter.isOnTheFly())); + List fixes = new ArrayList<>(createCastFixes(typeCast, realType, reporter.isOnTheFly(), alwaysFails)); if (reporter.isOnTheFly()) { fixes.add(createExplainFix(typeCast, new TrackingRunner.CastDfaProblemType())); } diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInstructionVisitor.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInstructionVisitor.java index 0120e01dce47..7b45e68075a6 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInstructionVisitor.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInstructionVisitor.java @@ -16,6 +16,7 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiTypesUtil; +import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.TypeConversionUtil; import com.intellij.util.ThreeState; import com.intellij.util.containers.ContainerUtil; @@ -35,6 +36,7 @@ final class DataFlowInstructionVisitor extends StandardInstructionVisitor { private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.dataFlow.DataFlowInstructionVisitor"); private final Map, StateInfo> myStateInfos = new LinkedHashMap<>(); private final Map myClassCastProblems = new HashMap<>(); + private final Map myRealOperandTypes = new HashMap<>(); private final Map myFailingCalls = new HashMap<>(); private final Map myConstantExpressions = new HashMap<>(); private final Map myOfNullableCalls = new HashMap<>(); @@ -156,8 +158,9 @@ final class DataFlowInstructionVisitor extends StandardInstructionVisitor { return myMethodReferenceResults; } - EntryStream getFailingCastExpressions() { - return EntryStream.of(myClassCastProblems).filterValues(StateInfo::shouldReport).mapValues(StateInfo::alwaysFails); + EntryStream> getFailingCastExpressions() { + return EntryStream.of(myClassCastProblems).filterValues(StateInfo::shouldReport).mapToValue( + (cast, info) -> Pair.create(info.alwaysFails(), myRealOperandTypes.getOrDefault(cast, TypeConstraint.empty()).getPsiType())); } Set getMutabilityViolations(boolean receiver) { @@ -193,6 +196,12 @@ final class DataFlowInstructionVisitor extends StandardInstructionVisitor { } } expression.accept(new ExpressionVisitor(value, memState)); + PsiElement parent = PsiUtil.skipParenthesizedExprUp(expression.getParent()); + if (parent instanceof PsiTypeCastExpression) { + TypeConstraint fact = memState.getValueFact(value, DfaFactType.TYPE_CONSTRAINT); + if (fact == null) fact = TypeConstraint.empty(); + myRealOperandTypes.merge((PsiTypeCastExpression)parent, fact, TypeConstraint::unite); + } if (range == null) { reportConstantExpressionValue(value, memState, expression); } diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaPsiUtil.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaPsiUtil.java index b3907058b61e..ac0378931264 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaPsiUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaPsiUtil.java @@ -533,4 +533,26 @@ public class DfaPsiUtil { } return Nullability.UNKNOWN; } + + /** + * Try to restore type parameters based on the expression type + * + * @param expression expression which type is a supertype of the type to generify + * @param type a type to generify + * @return a generified type, or original type if generification is not possible + */ + public static PsiType tryGenerify(PsiExpression expression, PsiType type) { + if (!(type instanceof PsiClassType)) { + return type; + } + PsiClassType classType = (PsiClassType)type; + if (!classType.isRaw()) { + return classType; + } + PsiClass psiClass = classType.resolve(); + if (psiClass == null) return classType; + PsiType expressionType = expression.getType(); + if (!(expressionType instanceof PsiClassType)) return classType; + return GenericsUtil.getExpectedGenericType(expression, psiClass, (PsiClassType)expressionType); + } } diff --git a/java/java-impl/src/com/intellij/codeInspection/ReplaceTypeInCastFix.java b/java/java-impl/src/com/intellij/codeInspection/ReplaceTypeInCastFix.java new file mode 100644 index 000000000000..6eab25619c37 --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInspection/ReplaceTypeInCastFix.java @@ -0,0 +1,44 @@ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.codeInspection; + +import com.intellij.openapi.project.Project; +import com.intellij.psi.JavaPsiFacade; +import com.intellij.psi.PsiElementFactory; +import com.intellij.psi.PsiType; +import com.intellij.psi.PsiTypeElement; +import com.intellij.util.ObjectUtils; +import com.siyeh.InspectionGadgetsBundle; +import org.jetbrains.annotations.NotNull; + +public class ReplaceTypeInCastFix implements LocalQuickFix { + private final String myExistingTypeText; + private final String myWantedTypeText; + private final String myWantedTypeCanonicalText; + + public ReplaceTypeInCastFix(PsiType existingType, PsiType wantedType) { + myExistingTypeText = existingType.getPresentableText(); + myWantedTypeText = wantedType.getPresentableText(); + myWantedTypeCanonicalText = wantedType.getCanonicalText(); + } + + @Override + @NotNull + public String getName() { + return InspectionGadgetsBundle.message("cast.conflicts.with.instanceof.quickfix1", myExistingTypeText, myWantedTypeText); + } + + @NotNull + @Override + public String getFamilyName() { + return "Replace cast type"; + } + + @Override + public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { + PsiTypeElement typeElement = ObjectUtils.tryCast(descriptor.getStartElement(), PsiTypeElement.class); + if (typeElement == null) return; + PsiElementFactory factory = JavaPsiFacade.getElementFactory(project); + PsiTypeElement replacement = factory.createTypeElement(factory.createTypeFromText(myWantedTypeCanonicalText, typeElement)); + typeElement.replace(replacement); + } +} diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspection.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspection.java index 302cc5fd3012..59b5dfeae3dd 100644 --- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspection.java @@ -136,15 +136,36 @@ public class DataFlowInspection extends DataFlowInspectionBase { @Override @NotNull - protected List createCastFixes(PsiTypeCastExpression castExpression, boolean onTheFly) { + protected List createCastFixes(PsiTypeCastExpression castExpression, + PsiType realType, + boolean onTheFly, + boolean alwaysFails) { List fixes = new ArrayList<>(); PsiExpression operand = castExpression.getOperand(); PsiTypeElement typeElement = castExpression.getCastType(); - if (typeElement != null && operand != null && !SideEffectChecker.mayHaveSideEffects(operand)) { - String suffix = " instanceof " + typeElement.getText(); - fixes.add(new AddAssertStatementFix(ParenthesesUtils.getText(operand, PsiPrecedenceUtil.RELATIONAL_PRECEDENCE) + suffix)); - if (onTheFly && SurroundWithIfFix.isAvailable(operand)) { - fixes.add(new SurroundWithIfFix(operand, suffix)); + if (typeElement != null && operand != null) { + if (!alwaysFails && !SideEffectChecker.mayHaveSideEffects(operand)) { + String suffix = " instanceof " + typeElement.getText(); + fixes.add(new AddAssertStatementFix(ParenthesesUtils.getText(operand, PsiPrecedenceUtil.RELATIONAL_PRECEDENCE) + suffix)); + if (onTheFly && SurroundWithIfFix.isAvailable(operand)) { + fixes.add(new SurroundWithIfFix(operand, suffix)); + } + } + if (realType != null) { + PsiType operandType = operand.getType(); + if (operandType != null) { + PsiType type = typeElement.getType(); + PsiType[] types = {realType}; + if (realType instanceof PsiIntersectionType) { + types = ((PsiIntersectionType)realType).getConjuncts(); + } + for (PsiType psiType : types) { + if (!psiType.isAssignableFrom(operandType)) { + psiType = DfaPsiUtil.tryGenerify(operand, psiType); + fixes.add(new ReplaceTypeInCastFix(type, psiType)); + } + } + } } } return fixes; diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/replaceTypeInCast/afterAssignment.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/replaceTypeInCast/afterAssignment.java new file mode 100644 index 000000000000..978284bb841d --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/replaceTypeInCast/afterAssignment.java @@ -0,0 +1,9 @@ +// "Replace 'Integer' with 'String' in cast" "true" +import java.util.*; + +class X { + void test() { + Object x = "foo"; + System.out.println((String)x); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/replaceTypeInCast/afterInstanceOf.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/replaceTypeInCast/afterInstanceOf.java new file mode 100644 index 000000000000..1a33ddfaf00d --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/replaceTypeInCast/afterInstanceOf.java @@ -0,0 +1,10 @@ +// "Replace 'LinkedList' with 'ArrayList' in cast" "true" +import java.util.*; + +class X { + void test(List x) { + if (x instanceof ArrayList) { + AbstractList list = (ArrayList)x; + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/replaceTypeInCast/afterIntersection.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/replaceTypeInCast/afterIntersection.java new file mode 100644 index 000000000000..2d990c6b4315 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/replaceTypeInCast/afterIntersection.java @@ -0,0 +1,10 @@ +// "Replace 'Integer' with 'Number' in cast" "true" +import java.util.*; + +class X { + void test(Object x) { + if (x instanceof Integer || x instanceof Long) { + System.out.println(((Number)x).longValue()); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/replaceTypeInCast/beforeAssignment.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/replaceTypeInCast/beforeAssignment.java new file mode 100644 index 000000000000..3bbe73a582dd --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/replaceTypeInCast/beforeAssignment.java @@ -0,0 +1,9 @@ +// "Replace 'Integer' with 'String' in cast" "true" +import java.util.*; + +class X { + void test() { + Object x = "foo"; + System.out.println((Integer)x); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/replaceTypeInCast/beforeInstanceOf.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/replaceTypeInCast/beforeInstanceOf.java new file mode 100644 index 000000000000..2a1c6471f13d --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/replaceTypeInCast/beforeInstanceOf.java @@ -0,0 +1,10 @@ +// "Replace 'LinkedList' with 'ArrayList' in cast" "true" +import java.util.*; + +class X { + void test(List x) { + if (x instanceof ArrayList) { + AbstractList list = (LinkedList)x; + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/replaceTypeInCast/beforeIntersection.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/replaceTypeInCast/beforeIntersection.java new file mode 100644 index 000000000000..42ac09591612 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/replaceTypeInCast/beforeIntersection.java @@ -0,0 +1,10 @@ +// "Replace 'Integer' with 'Number' in cast" "true" +import java.util.*; + +class X { + void test(Object x) { + if (x instanceof Integer || x instanceof Long) { + System.out.println(((Integer)x).longValue()); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/replaceTypeInCast/beforeNotInstanceOf.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/replaceTypeInCast/beforeNotInstanceOf.java new file mode 100644 index 000000000000..62ad9b532795 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/replaceTypeInCast/beforeNotInstanceOf.java @@ -0,0 +1,10 @@ +// "Fix all 'Constant conditions & exceptions' problems in file" "false" +import java.util.*; + +class X { + void test(Object x) { + if (!(x instanceof Number)) { + System.out.println(((Integer)x).longValue()); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/quickFix/ReplaceTypeInCastFixTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/quickFix/ReplaceTypeInCastFixTest.java new file mode 100644 index 000000000000..f80366ad2e19 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/quickFix/ReplaceTypeInCastFixTest.java @@ -0,0 +1,43 @@ +/* + * Copyright 2000-2017 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.java.codeInsight.daemon.quickFix; + +import com.intellij.codeInsight.daemon.quickFix.LightQuickFixParameterizedTestCase; +import com.intellij.codeInspection.LocalInspectionTool; +import com.intellij.codeInspection.dataFlow.DataFlowInspection; +import com.intellij.testFramework.LightProjectDescriptor; +import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase; +import org.jetbrains.annotations.NotNull; + +public class ReplaceTypeInCastFixTest extends LightQuickFixParameterizedTestCase { + @NotNull + @Override + protected LocalInspectionTool[] configureLocalInspectionTools() { + return new LocalInspectionTool[]{new DataFlowInspection()}; + } + + @NotNull + @Override + protected LightProjectDescriptor getProjectDescriptor() { + return LightJavaCodeInsightFixtureTestCase.JAVA_10_ANNOTATED; + } + + @Override + protected String getBasePath() { + return "/codeInsight/daemonCodeAnalyzer/quickFix/replaceTypeInCast"; + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTestSuite.java b/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTestSuite.java index e921ae011dcf..a1129d593c9e 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTestSuite.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTestSuite.java @@ -69,7 +69,8 @@ import org.junit.runners.Suite; RedundantInstanceofFixTest.class, ReplaceComputeWithComputeIfPresentFixTest.class, DeleteSwitchLabelFixTest.class, - DeleteRedundantUpdateFixTest.class + DeleteRedundantUpdateFixTest.class, + ReplaceTypeInCastFixTest.class }) public class DataFlowInspectionTestSuite { } diff --git a/java/java-tests/testSrc/com/intellij/java/propertyBased/JavaIntentionPolicy.java b/java/java-tests/testSrc/com/intellij/java/propertyBased/JavaIntentionPolicy.java index 8ec7e1060ed6..f99d002d89f8 100644 --- a/java/java-tests/testSrc/com/intellij/java/propertyBased/JavaIntentionPolicy.java +++ b/java/java-tests/testSrc/com/intellij/java/propertyBased/JavaIntentionPolicy.java @@ -57,6 +57,7 @@ class JavaIntentionPolicy extends IntentionPolicy { actionText.equals("Split into declaration and initialization") || // TODO: remove when IDEA-179081 is fixed actionText.matches("Replace with throws .*") || //may break catches with explicit exceptions actionText.equals("Generate 'clone()' method which always throws exception") || // IDEA-207048 + actionText.matches("Replace '.+' with '.+' in cast") || // can produce uncompilable code by design actionText.matches("Replace with '(new .+\\[]|.+\\[]::new)'"); // Suspicious toArray may introduce compilation error }