[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");