[FIR] Fix `usedAsExpression` calculating for PARENTHESIZED and POSTFIX_EXPRESSION
^KT-56615 Fixed
diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java
index 1078a28..44741dd 100644
--- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java
+++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java
@@ -5383,6 +5383,12 @@
}
@Test
+ @TestMetadata("UselessCastOnSecondSmartcast.kt")
+ public void testUselessCastOnSecondSmartcast() throws Exception {
+ runTest("compiler/testData/diagnostics/tests/cast/UselessCastOnSecondSmartcast.kt");
+ }
+
+ @Test
@TestMetadata("UselessSafeCast.kt")
public void testUselessSafeCast() throws Exception {
runTest("compiler/testData/diagnostics/tests/cast/UselessSafeCast.kt");
diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java
index 162fcf9..5046fd6 100644
--- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java
+++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java
@@ -5383,6 +5383,12 @@
}
@Test
+ @TestMetadata("UselessCastOnSecondSmartcast.kt")
+ public void testUselessCastOnSecondSmartcast() throws Exception {
+ runTest("compiler/testData/diagnostics/tests/cast/UselessCastOnSecondSmartcast.kt");
+ }
+
+ @Test
@TestMetadata("UselessSafeCast.kt")
public void testUselessSafeCast() throws Exception {
runTest("compiler/testData/diagnostics/tests/cast/UselessSafeCast.kt");
diff --git a/compiler/fir/analysis-tests/testData/resolve/checkers/redundantNullCheckOnAsCast.kt b/compiler/fir/analysis-tests/testData/resolve/checkers/redundantNullCheckOnAsCast.kt
index fd5819c..fe7df0c 100644
--- a/compiler/fir/analysis-tests/testData/resolve/checkers/redundantNullCheckOnAsCast.kt
+++ b/compiler/fir/analysis-tests/testData/resolve/checkers/redundantNullCheckOnAsCast.kt
@@ -2,7 +2,7 @@
fun test_1(a: Any?) {
(a as String?)!!
- (a as? String)!!
+ (a <!USELESS_CAST!>as? String<!>)!!
}
fun test_2(a: Any?) {
diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java
index 92ef68f..05870ef 100644
--- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java
+++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java
@@ -5383,6 +5383,12 @@
}
@Test
+ @TestMetadata("UselessCastOnSecondSmartcast.kt")
+ public void testUselessCastOnSecondSmartcast() throws Exception {
+ runTest("compiler/testData/diagnostics/tests/cast/UselessCastOnSecondSmartcast.kt");
+ }
+
+ @Test
@TestMetadata("UselessSafeCast.kt")
public void testUselessSafeCast() throws Exception {
runTest("compiler/testData/diagnostics/tests/cast/UselessSafeCast.kt");
diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java
index 3c5f91f..3e56e4e 100644
--- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java
+++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java
@@ -5389,6 +5389,12 @@
}
@Test
+ @TestMetadata("UselessCastOnSecondSmartcast.kt")
+ public void testUselessCastOnSecondSmartcast() throws Exception {
+ runTest("compiler/testData/diagnostics/tests/cast/UselessCastOnSecondSmartcast.kt");
+ }
+
+ @Test
@TestMetadata("UselessSafeCast.kt")
public void testUselessSafeCast() throws Exception {
runTest("compiler/testData/diagnostics/tests/cast/UselessSafeCast.kt");
diff --git a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/LightTreeRawFirExpressionBuilder.kt b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/LightTreeRawFirExpressionBuilder.kt
index 5cf8f80..0b06b5e 100644
--- a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/LightTreeRawFirExpressionBuilder.kt
+++ b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/LightTreeRawFirExpressionBuilder.kt
@@ -1393,19 +1393,23 @@
private val LighterASTNode.usedAsExpression: Boolean
get() {
- var parent = getParent() ?: return true
- while (parent.elementType == ANNOTATED_EXPRESSION ||
- parent.elementType == LABELED_EXPRESSION
- ) {
- parent = parent.getParent() ?: return true
+ var relevantParent = getParent() ?: return true
+ while (true) {
+ relevantParent = when (relevantParent.elementType) {
+ ANNOTATED_EXPRESSION,
+ LABELED_EXPRESSION,
+ PARENTHESIZED,
+ POSTFIX_EXPRESSION -> relevantParent.getParent() ?: return true
+ THEN,
+ ELSE,
+ WHEN_ENTRY -> relevantParent.getParent()?.getParent() ?: return true
+ BLOCK -> return false
+ else -> break
+ }
}
- val parentTokenType = parent.tokenType
- if (parentTokenType == BLOCK) return false
- if (parentTokenType == THEN || parentTokenType == ELSE || parentTokenType == WHEN_ENTRY) {
- return parent.getParent()?.usedAsExpression ?: true
- }
- if (parentTokenType != BODY) return true
- val type = parent.getParent()?.tokenType ?: return true
+
+ if (relevantParent.tokenType != BODY) return true
+ val type = relevantParent.getParent()?.tokenType ?: return true
return !(type == FOR || type == WHILE || type == DO_WHILE)
}
diff --git a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiRawFirBuilder.kt b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiRawFirBuilder.kt
index 60ce806..759ed63 100644
--- a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiRawFirBuilder.kt
+++ b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiRawFirBuilder.kt
@@ -2540,22 +2540,25 @@
private val KtExpression.usedAsExpression: Boolean
get() {
- var parent = parent
- while (parent.elementType == KtNodeTypes.ANNOTATED_EXPRESSION ||
- parent.elementType == KtNodeTypes.LABELED_EXPRESSION
- ) {
- parent = parent.parent
- }
- if (parent is KtBlockExpression) return false
- when (parent.elementType) {
- KtNodeTypes.THEN, KtNodeTypes.ELSE, KtNodeTypes.WHEN_ENTRY -> {
- return (parent.parent as? KtExpression)?.usedAsExpression ?: true
+ var relevantParent = parent
+ while (true) {
+ relevantParent = when (relevantParent.elementType) {
+ KtNodeTypes.ANNOTATED_EXPRESSION,
+ KtNodeTypes.LABELED_EXPRESSION,
+ KtNodeTypes.PARENTHESIZED,
+ KtNodeTypes.POSTFIX_EXPRESSION -> relevantParent.parent
+ KtNodeTypes.THEN,
+ KtNodeTypes.ELSE,
+ KtNodeTypes.WHEN_ENTRY -> relevantParent.parent.parent
+ KtNodeTypes.BLOCK -> return false
+ else -> break
}
}
- if (parent is KtScriptInitializer) return false
+
+ if (relevantParent is KtScriptInitializer) return false
// Here we check that when used is a single statement of a loop
- if (parent !is KtContainerNodeForControlStructureBody) return true
- val type = parent.parent.elementType
+ if (relevantParent !is KtContainerNodeForControlStructureBody) return true
+ val type = relevantParent.parent.elementType
return !(type == KtNodeTypes.FOR || type == KtNodeTypes.WHILE || type == KtNodeTypes.DO_WHILE)
}
diff --git a/compiler/testData/diagnostics/tests/cast/UselessCastOnSecondSmartcast.fir.kt b/compiler/testData/diagnostics/tests/cast/UselessCastOnSecondSmartcast.fir.kt
new file mode 100644
index 0000000..7a04927
--- /dev/null
+++ b/compiler/testData/diagnostics/tests/cast/UselessCastOnSecondSmartcast.fir.kt
@@ -0,0 +1,30 @@
+// ISSUE: KT-56615
+
+fun test_1(a: Any?) {
+ (a as String?)!!
+ a.length
+ (a <!USELESS_CAST!>as? String<!>)!!
+ a.length
+}
+
+fun test_3(a: Any?) {
+ a as String
+ a <!USELESS_CAST!>as String<!>
+}
+
+fun test_4(a: Any?) {
+ a as String
+ a <!USELESS_CAST!>as? String<!>
+}
+
+fun test_5(a: Any?) {
+ (a as? String)!!
+ a.length
+ (a <!USELESS_CAST!>as String<!>)
+}
+
+fun test_6(a: Any?) {
+ (a as? String)!!
+ a.length
+ (a <!USELESS_CAST!>as? String<!>)
+}
diff --git a/compiler/testData/diagnostics/tests/cast/UselessCastOnSecondSmartcast.kt b/compiler/testData/diagnostics/tests/cast/UselessCastOnSecondSmartcast.kt
new file mode 100644
index 0000000..8fbf9e4a
--- /dev/null
+++ b/compiler/testData/diagnostics/tests/cast/UselessCastOnSecondSmartcast.kt
@@ -0,0 +1,30 @@
+// ISSUE: KT-56615
+
+fun test_1(a: Any?) {
+ (a as String?)!!
+ a<!UNSAFE_CALL!>.<!>length
+ (a <!USELESS_CAST!>as? String<!>)!!
+ <!DEBUG_INFO_SMARTCAST!>a<!>.length
+}
+
+fun test_3(a: Any?) {
+ a as String
+ a <!USELESS_CAST!>as String<!>
+}
+
+fun test_4(a: Any?) {
+ a as String
+ a <!USELESS_CAST!>as? String<!>
+}
+
+fun test_5(a: Any?) {
+ (a as? String)!!
+ <!DEBUG_INFO_SMARTCAST!>a<!>.length
+ (a <!USELESS_CAST!>as String<!>)
+}
+
+fun test_6(a: Any?) {
+ (a as? String)!!
+ <!DEBUG_INFO_SMARTCAST!>a<!>.length
+ (a <!USELESS_CAST!>as? String<!>)
+}
diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java
index 6953bec..ece85a8 100644
--- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java
+++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java
@@ -5389,6 +5389,12 @@
}
@Test
+ @TestMetadata("UselessCastOnSecondSmartcast.kt")
+ public void testUselessCastOnSecondSmartcast() throws Exception {
+ runTest("compiler/testData/diagnostics/tests/cast/UselessCastOnSecondSmartcast.kt");
+ }
+
+ @Test
@TestMetadata("UselessSafeCast.kt")
public void testUselessSafeCast() throws Exception {
runTest("compiler/testData/diagnostics/tests/cast/UselessSafeCast.kt");