diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/KotlinJvmCheckerProvider.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/KotlinJvmCheckerProvider.kt index 870e0933584..a521cc53a70 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/KotlinJvmCheckerProvider.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/KotlinJvmCheckerProvider.kt @@ -223,7 +223,7 @@ public class JavaNullabilityWarningsChecker : AdditionalTypeChecker { when (expression) { is JetPostfixExpression -> if (expression.getOperationToken() == JetTokens.EXCLEXCL) { - val baseExpression = expression.getBaseExpression() + val baseExpression = expression.getBaseExpression() ?: return val baseExpressionType = c.trace.getType(baseExpression) ?: return doIfNotNull( DataFlowValueFactory.createDataFlowValue(baseExpression, baseExpressionType, c), diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/JetPostfixExpression.java b/compiler/frontend/src/org/jetbrains/kotlin/psi/JetPostfixExpression.java index f9439f8c431..dca600ad638 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/JetPostfixExpression.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/JetPostfixExpression.java @@ -17,7 +17,9 @@ package org.jetbrains.kotlin.psi; import com.intellij.lang.ASTNode; +import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public class JetPostfixExpression extends JetUnaryExpression { public JetPostfixExpression(@NotNull ASTNode node) { @@ -25,11 +27,9 @@ public class JetPostfixExpression extends JetUnaryExpression { } @Override - @NotNull + @Nullable @IfNotParsed public JetExpression getBaseExpression() { - JetExpression answer = findChildByClass(JetExpression.class); - assert answer != null; - return answer; + return PsiTreeUtil.getPrevSiblingOfType(getOperationReference(), JetExpression.class); } @Override diff --git a/compiler/testData/cfg/bugs/kt7761.instructions b/compiler/testData/cfg/bugs/kt7761.instructions new file mode 100644 index 00000000000..1adab405bd9 --- /dev/null +++ b/compiler/testData/cfg/bugs/kt7761.instructions @@ -0,0 +1,81 @@ +== UnitIncDec == +class UnitIncDec() { + fun inc() : Unit {} + fun dec() : Unit {} +} +--------------------- +L0: + 1 +L1: + NEXT:[] +error: + PREV:[] +sink: + PREV:[, ] +===================== +== inc == +fun inc() : Unit {} +--------------------- +L0: + 1 + 2 mark({}) + read (Unit) +L1: + 1 NEXT:[] +error: + PREV:[] +sink: + PREV:[, ] +===================== +== dec == +fun dec() : Unit {} +--------------------- +L0: + 1 + 2 mark({}) + read (Unit) +L1: + 1 NEXT:[] +error: + PREV:[] +sink: + PREV:[, ] +===================== +== testUnitIncDec == +fun testUnitIncDec() { + var x = UnitIncDec() + x = x++ +} +--------------------- +L0: + 1 + 2 mark({ var x = UnitIncDec() x = x++ }) + v(var x = UnitIncDec()) + mark(UnitIncDec()) + call(UnitIncDec(), ) -> + w(x|) + mark() + magic[UNRESOLVED_CALL]() -> + mark(x<) + call(x<, |) -> + magic[VALUE_CONSUMER](>++|!) -> + mark(x++) + call(x++, |) -> + mark(/error>) + magic[UNRESOLVED_CALL](/error>) -> + magic[VALUE_CONSUMER](/error>|) -> + mark(x++) + call(x++, |) -> + mark(/warning>) + magic[UNRESOLVED_CALL](/warning>) -> + magic[VALUE_CONSUMER](/warning>|) -> + mark(x++) + call(x++, |) -> + w(x|) +L1: + 1 NEXT:[] +error: + PREV:[] +sink: + PREV:[, ] +===================== diff --git a/compiler/testData/cfg/bugs/kt7761.kt b/compiler/testData/cfg/bugs/kt7761.kt new file mode 100644 index 00000000000..8c45047589e --- /dev/null +++ b/compiler/testData/cfg/bugs/kt7761.kt @@ -0,0 +1,9 @@ +class UnitIncDec() { + fun inc() : Unit {} + fun dec() : Unit {} +} + +fun testUnitIncDec() { + var x = UnitIncDec() + x = x++ +} \ No newline at end of file diff --git a/compiler/testData/cfg/bugs/kt7761.values b/compiler/testData/cfg/bugs/kt7761.values new file mode 100644 index 00000000000..eb1762564fe --- /dev/null +++ b/compiler/testData/cfg/bugs/kt7761.values @@ -0,0 +1,36 @@ +== UnitIncDec == +class UnitIncDec() { + fun inc() : Unit {} + fun dec() : Unit {} +} +--------------------- +===================== +== inc == +fun inc() : Unit {} +--------------------- +===================== +== dec == +fun dec() : Unit {} +--------------------- +===================== +== testUnitIncDec == +fun testUnitIncDec() { + var x = UnitIncDec() + x = x++ +} +--------------------- + : * NEW: magic[VALUE_CONSUMER](/warning>|) -> + : * NEW: magic[VALUE_CONSUMER](>++|!) -> + : * NEW: magic[VALUE_CONSUMER](/error>|) -> +UnitIncDec() : UnitIncDec NEW: call(UnitIncDec(), ) -> + : * NEW: magic[UNRESOLVED_CALL]() -> +x< : * NEW: call(x<, |) -> +>++ !: * +x++ : * NEW: call(x++, |) -> +/error> : * NEW: magic[UNRESOLVED_CALL](/error>) -> +x++ : * NEW: call(x++, |) -> +/warning> : * NEW: magic[UNRESOLVED_CALL](/warning>) -> +x++ : UnitIncDec NEW: call(x++, |) -> +x = x++ !: * +{ var x = UnitIncDec() x = x++ } !: * COPY +===================== diff --git a/compiler/tests/org/jetbrains/kotlin/cfg/ControlFlowTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/cfg/ControlFlowTestGenerated.java index b82b8b574ec..8d22e020d0c 100644 --- a/compiler/tests/org/jetbrains/kotlin/cfg/ControlFlowTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/cfg/ControlFlowTestGenerated.java @@ -144,6 +144,12 @@ public class ControlFlowTestGenerated extends AbstractControlFlowTest { String fileName = JetTestUtils.navigationMetadata("compiler/testData/cfg/bugs/jumpToOuterScope.kt"); doTest(fileName); } + + @TestMetadata("kt7761.kt") + public void testKt7761() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/cfg/bugs/kt7761.kt"); + doTest(fileName); + } } @TestMetadata("compiler/testData/cfg/controlStructures") diff --git a/compiler/tests/org/jetbrains/kotlin/cfg/PseudoValueTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/cfg/PseudoValueTestGenerated.java index 3091c05e5d9..2cc9a7b5bd3 100644 --- a/compiler/tests/org/jetbrains/kotlin/cfg/PseudoValueTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/cfg/PseudoValueTestGenerated.java @@ -146,6 +146,12 @@ public class PseudoValueTestGenerated extends AbstractPseudoValueTest { String fileName = JetTestUtils.navigationMetadata("compiler/testData/cfg/bugs/jumpToOuterScope.kt"); doTest(fileName); } + + @TestMetadata("kt7761.kt") + public void testKt7761() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/cfg/bugs/kt7761.kt"); + doTest(fileName); + } } @TestMetadata("compiler/testData/cfg/controlStructures") diff --git a/idea/ide-common/src/org/jetbrains/kotlin/resolve/lazy/PartialBodyResolveFilter.kt b/idea/ide-common/src/org/jetbrains/kotlin/resolve/lazy/PartialBodyResolveFilter.kt index 70b5c4928d7..271456c4dc6 100644 --- a/idea/ide-common/src/org/jetbrains/kotlin/resolve/lazy/PartialBodyResolveFilter.kt +++ b/idea/ide-common/src/org/jetbrains/kotlin/resolve/lazy/PartialBodyResolveFilter.kt @@ -174,7 +174,7 @@ class PartialBodyResolveFilter( expression.acceptChildren(this) if (expression.getOperationToken() == JetTokens.EXCLEXCL) { - addIfCanBeSmartCast(expression.getBaseExpression()) + addIfCanBeSmartCast(expression.getBaseExpression() ?: return) } } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/intentions/OperatorToFunctionIntention.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/intentions/OperatorToFunctionIntention.kt index bf60f29c01d..9683c17605e 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/intentions/OperatorToFunctionIntention.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/intentions/OperatorToFunctionIntention.kt @@ -40,6 +40,7 @@ public class OperatorToFunctionIntention : JetSelfTargetingIntention true else -> false @@ -98,7 +99,7 @@ public class OperatorToFunctionIntention : JetSelfTargetingIntention "inc()" diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/refactoring/JetNameSuggester.java b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/refactoring/JetNameSuggester.java index 5d4c7659dce..0595744b124 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/refactoring/JetNameSuggester.java +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/refactoring/JetNameSuggester.java @@ -224,7 +224,12 @@ public class JetNameSuggester { return matcher.replaceAll(""); } - private static void addNamesForExpression(final ArrayList result, JetExpression expression, final JetNameValidator validator) { + private static void addNamesForExpression( + final ArrayList result, + @Nullable JetExpression expression, + final JetNameValidator validator) { + if (expression == null) return; + expression.accept(new JetVisitorVoid() { @Override public void visitQualifiedExpression(@NotNull JetQualifiedExpression expression) { diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/intentions/DoubleBangToIfThenIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/intentions/DoubleBangToIfThenIntention.kt index 014e0a1419e..44fe3666ee1 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/intentions/DoubleBangToIfThenIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/intentions/DoubleBangToIfThenIntention.kt @@ -37,11 +37,14 @@ import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsStatement public class DoubleBangToIfThenIntention : JetSelfTargetingRangeIntention(javaClass(), "Replace '!!' expression with 'if' expression") { override fun applicabilityRange(element: JetPostfixExpression): TextRange? { - return if (element.getOperationToken() == JetTokens.EXCLEXCL) element.getOperationReference().getTextRange() else null + return if (element.getOperationToken() == JetTokens.EXCLEXCL && element.getBaseExpression() != null) + element.getOperationReference().getTextRange() + else + null } override fun applyTo(element: JetPostfixExpression, editor: Editor) { - val base = JetPsiUtil.safeDeparenthesize(element.getBaseExpression()) + val base = JetPsiUtil.safeDeparenthesize(element.getBaseExpression()!!) val expressionText = formatForUseInExceptionArgument(base.getText()!!) val defaultException = JetPsiFactory(element).createExpression("throw NullPointerException()") diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/ExclExclCallFix.java b/idea/src/org/jetbrains/kotlin/idea/quickfix/ExclExclCallFix.java index 43d6411b1ec..97c3d2aa7f7 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/ExclExclCallFix.java +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/ExclExclCallFix.java @@ -168,7 +168,7 @@ public class ExclExclCallFix implements IntentionAction { PsiElement parent = exclExclElement.getParent(); if (parent != null) { PsiElement operationParent = parent.getParent(); - if (operationParent instanceof JetPostfixExpression) { + if (operationParent instanceof JetPostfixExpression && ((JetPostfixExpression) operationParent).getBaseExpression() != null) { return (JetPostfixExpression) operationParent; } }