[AA] handles FIR isUsedAsExpression for return within function block
For the following example:
```
fun foo(bar: Int) {
<expr>if (bar == 4) return "Four"
else return "Int"</expr>
}
```
AA FE1.0 `isUsedAsExpression` returns `false`.
Since the current AA FIR `isUsedAsExpression` returns `true` for the
above example, this commit fixes it.
diff --git a/analysis/analysis-api-fe10/tests-gen/org/jetbrains/kotlin/analysis/api/fe10/test/cases/generated/cases/components/expressionInfoProvider/Fe10IdeNormalAnalysisSourceModuleIsUsedAsExpressionTestGenerated.java b/analysis/analysis-api-fe10/tests-gen/org/jetbrains/kotlin/analysis/api/fe10/test/cases/generated/cases/components/expressionInfoProvider/Fe10IdeNormalAnalysisSourceModuleIsUsedAsExpressionTestGenerated.java
index d4c7338..bc6fc1f 100644
--- a/analysis/analysis-api-fe10/tests-gen/org/jetbrains/kotlin/analysis/api/fe10/test/cases/generated/cases/components/expressionInfoProvider/Fe10IdeNormalAnalysisSourceModuleIsUsedAsExpressionTestGenerated.java
+++ b/analysis/analysis-api-fe10/tests-gen/org/jetbrains/kotlin/analysis/api/fe10/test/cases/generated/cases/components/expressionInfoProvider/Fe10IdeNormalAnalysisSourceModuleIsUsedAsExpressionTestGenerated.java
@@ -959,6 +959,18 @@
}
@Test
+ @TestMetadata("function_body_with_if.kt")
+ public void testFunction_body_with_if() throws Exception {
+ runTest("analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/function_body_with_if.kt");
+ }
+
+ @Test
+ @TestMetadata("function_equal_block_with_if.kt")
+ public void testFunction_equal_block_with_if() throws Exception {
+ runTest("analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/function_equal_block_with_if.kt");
+ }
+
+ @Test
@TestMetadata("ifBranches_unused.kt")
public void testIfBranches_unused() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/ifBranches_unused.kt");
@@ -1511,12 +1523,24 @@
}
@Test
+ @TestMetadata("return_inside_if.kt")
+ public void testReturn_inside_if() throws Exception {
+ runTest("analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/return_inside_if.kt");
+ }
+
+ @Test
@TestMetadata("return_value.kt")
public void testReturn_value() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/return_value.kt");
}
@Test
+ @TestMetadata("return_with_if.kt")
+ public void testReturn_with_if() throws Exception {
+ runTest("analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/return_with_if.kt");
+ }
+
+ @Test
@TestMetadata("run_block.kt")
public void testRun_block() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/run_block.kt");
diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirExpressionInfoProvider.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirExpressionInfoProvider.kt
index de05b88..9f7d8bc 100644
--- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirExpressionInfoProvider.kt
+++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirExpressionInfoProvider.kt
@@ -209,8 +209,6 @@
is KtFunctionLiteral ->
parent.bodyBlockExpression == child && !returnsUnit(parent)
- // Named functions do not use their bodies if the function itself returns unit
- // UNLESS it's an expression body/lambda of type Unit.
/** See [doesNamedFunctionUseBody] */
is KtNamedFunction ->
doesNamedFunctionUseBody(parent, child)
@@ -402,23 +400,26 @@
}
/**
- * Named functions do not consider their bodies used if the function itself
- * returns Unit UNLESS the function body is an expression body and the body is
- * of type Unit.
+ * Returns whether the function uses its body as an expression (i.e., the function uses the result value of the expression) or not.
+ *
+ * Named functions do not consider their bodies used if
+ * - the function body is a block e.g., `fun foo(): Int { return bar }` or
+ * - the function itself returns Unit
*/
-private fun doesNamedFunctionUseBody(namedFunction: KtNamedFunction, body: PsiElement): Boolean =
- when {
- !returnsUnit(namedFunction) ->
- true
- namedFunction.bodyBlockExpression == body ->
- false
- namedFunction.bodyExpression == body ->
- analyze(namedFunction) {
- (body as KtExpression).getKtType()?.isUnit == true
- }
- else ->
- false
- }
+private fun doesNamedFunctionUseBody(namedFunction: KtNamedFunction, body: PsiElement): Boolean = when {
+ // The body is a block expression e.g., fun foo(): Int { return bar }
+ namedFunction.bodyBlockExpression == body ->
+ false
+ // Note that `namedFunction.hasBlockBody() == false` means the function definition uses `=` e.g., fun foo() = bar
+ !returnsUnit(namedFunction) ->
+ true
+ namedFunction.bodyExpression == body ->
+ analyze(namedFunction) {
+ (body as KtExpression).getKtType()?.isUnit == true
+ }
+ else ->
+ false
+}
private fun KtAnalysisSession.isSimpleVariableAccessCall(reference: KtReferenceExpression): Boolean =
diff --git a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/expressionInfoProvider/FirIdeDependentAnalysisSourceModuleIsUsedAsExpressionTestGenerated.java b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/expressionInfoProvider/FirIdeDependentAnalysisSourceModuleIsUsedAsExpressionTestGenerated.java
index 2f1ed27..7d43c7c 100644
--- a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/expressionInfoProvider/FirIdeDependentAnalysisSourceModuleIsUsedAsExpressionTestGenerated.java
+++ b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/expressionInfoProvider/FirIdeDependentAnalysisSourceModuleIsUsedAsExpressionTestGenerated.java
@@ -959,6 +959,18 @@
}
@Test
+ @TestMetadata("function_body_with_if.kt")
+ public void testFunction_body_with_if() throws Exception {
+ runTest("analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/function_body_with_if.kt");
+ }
+
+ @Test
+ @TestMetadata("function_equal_block_with_if.kt")
+ public void testFunction_equal_block_with_if() throws Exception {
+ runTest("analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/function_equal_block_with_if.kt");
+ }
+
+ @Test
@TestMetadata("ifBranches_unused.kt")
public void testIfBranches_unused() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/ifBranches_unused.kt");
@@ -1511,12 +1523,24 @@
}
@Test
+ @TestMetadata("return_inside_if.kt")
+ public void testReturn_inside_if() throws Exception {
+ runTest("analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/return_inside_if.kt");
+ }
+
+ @Test
@TestMetadata("return_value.kt")
public void testReturn_value() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/return_value.kt");
}
@Test
+ @TestMetadata("return_with_if.kt")
+ public void testReturn_with_if() throws Exception {
+ runTest("analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/return_with_if.kt");
+ }
+
+ @Test
@TestMetadata("run_block.kt")
public void testRun_block() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/run_block.kt");
diff --git a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/expressionInfoProvider/FirIdeNormalAnalysisSourceModuleIsUsedAsExpressionTestGenerated.java b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/expressionInfoProvider/FirIdeNormalAnalysisSourceModuleIsUsedAsExpressionTestGenerated.java
index 936af65..94d5ad7 100644
--- a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/expressionInfoProvider/FirIdeNormalAnalysisSourceModuleIsUsedAsExpressionTestGenerated.java
+++ b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/expressionInfoProvider/FirIdeNormalAnalysisSourceModuleIsUsedAsExpressionTestGenerated.java
@@ -959,6 +959,18 @@
}
@Test
+ @TestMetadata("function_body_with_if.kt")
+ public void testFunction_body_with_if() throws Exception {
+ runTest("analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/function_body_with_if.kt");
+ }
+
+ @Test
+ @TestMetadata("function_equal_block_with_if.kt")
+ public void testFunction_equal_block_with_if() throws Exception {
+ runTest("analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/function_equal_block_with_if.kt");
+ }
+
+ @Test
@TestMetadata("ifBranches_unused.kt")
public void testIfBranches_unused() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/ifBranches_unused.kt");
@@ -1511,12 +1523,24 @@
}
@Test
+ @TestMetadata("return_inside_if.kt")
+ public void testReturn_inside_if() throws Exception {
+ runTest("analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/return_inside_if.kt");
+ }
+
+ @Test
@TestMetadata("return_value.kt")
public void testReturn_value() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/return_value.kt");
}
@Test
+ @TestMetadata("return_with_if.kt")
+ public void testReturn_with_if() throws Exception {
+ runTest("analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/return_with_if.kt");
+ }
+
+ @Test
@TestMetadata("run_block.kt")
public void testRun_block() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/run_block.kt");
diff --git a/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/components/expressionInfoProvider/FirStandaloneNormalAnalysisSourceModuleIsUsedAsExpressionTestGenerated.java b/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/components/expressionInfoProvider/FirStandaloneNormalAnalysisSourceModuleIsUsedAsExpressionTestGenerated.java
index 1970b25..66a4628 100644
--- a/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/components/expressionInfoProvider/FirStandaloneNormalAnalysisSourceModuleIsUsedAsExpressionTestGenerated.java
+++ b/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/components/expressionInfoProvider/FirStandaloneNormalAnalysisSourceModuleIsUsedAsExpressionTestGenerated.java
@@ -959,6 +959,18 @@
}
@Test
+ @TestMetadata("function_body_with_if.kt")
+ public void testFunction_body_with_if() throws Exception {
+ runTest("analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/function_body_with_if.kt");
+ }
+
+ @Test
+ @TestMetadata("function_equal_block_with_if.kt")
+ public void testFunction_equal_block_with_if() throws Exception {
+ runTest("analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/function_equal_block_with_if.kt");
+ }
+
+ @Test
@TestMetadata("ifBranches_unused.kt")
public void testIfBranches_unused() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/ifBranches_unused.kt");
@@ -1511,12 +1523,24 @@
}
@Test
+ @TestMetadata("return_inside_if.kt")
+ public void testReturn_inside_if() throws Exception {
+ runTest("analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/return_inside_if.kt");
+ }
+
+ @Test
@TestMetadata("return_value.kt")
public void testReturn_value() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/return_value.kt");
}
@Test
+ @TestMetadata("return_with_if.kt")
+ public void testReturn_with_if() throws Exception {
+ runTest("analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/return_with_if.kt");
+ }
+
+ @Test
@TestMetadata("run_block.kt")
public void testRun_block() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/run_block.kt");
diff --git a/analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/function_body_with_if.kt b/analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/function_body_with_if.kt
new file mode 100644
index 0000000..3aa6629
--- /dev/null
+++ b/analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/function_body_with_if.kt
@@ -0,0 +1,5 @@
+fun test(n: Int) =
+ <expr>if (n == 1)
+ "one"
+ else
+ "two"</expr>
\ No newline at end of file
diff --git a/analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/function_body_with_if.txt b/analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/function_body_with_if.txt
new file mode 100644
index 0000000..7618937
--- /dev/null
+++ b/analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/function_body_with_if.txt
@@ -0,0 +1,6 @@
+expression: IF
+text: if (n == 1)
+ "one"
+ else
+ "two"
+isUsedAsExpression: true
diff --git a/analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/function_equal_block_with_if.kt b/analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/function_equal_block_with_if.kt
new file mode 100644
index 0000000..1eb5f32
--- /dev/null
+++ b/analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/function_equal_block_with_if.kt
@@ -0,0 +1,6 @@
+fun test(n: Int) = {
+ <expr>if (n == 1)
+ "one"
+ else
+ "two"</expr>
+}
\ No newline at end of file
diff --git a/analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/function_equal_block_with_if.txt b/analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/function_equal_block_with_if.txt
new file mode 100644
index 0000000..7618937
--- /dev/null
+++ b/analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/function_equal_block_with_if.txt
@@ -0,0 +1,6 @@
+expression: IF
+text: if (n == 1)
+ "one"
+ else
+ "two"
+isUsedAsExpression: true
diff --git a/analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/return_inside_if.kt b/analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/return_inside_if.kt
new file mode 100644
index 0000000..ec7e387
--- /dev/null
+++ b/analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/return_inside_if.kt
@@ -0,0 +1,6 @@
+fun test(n: Int): String {
+ if (n == 1)
+ <expr>return "one"</expr>
+ else
+ return "two"
+}
\ No newline at end of file
diff --git a/analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/return_inside_if.txt b/analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/return_inside_if.txt
new file mode 100644
index 0000000..f543237
--- /dev/null
+++ b/analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/return_inside_if.txt
@@ -0,0 +1,3 @@
+expression: RETURN
+text: return "one"
+isUsedAsExpression: false
diff --git a/analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/return_with_if.kt b/analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/return_with_if.kt
new file mode 100644
index 0000000..8217d96
--- /dev/null
+++ b/analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/return_with_if.kt
@@ -0,0 +1,6 @@
+fun test(n: Int): String {
+ <expr>if (n == 1)
+ return "one"
+ else
+ return "two"</expr>
+}
\ No newline at end of file
diff --git a/analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/return_with_if.txt b/analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/return_with_if.txt
new file mode 100644
index 0000000..dc0fde4
--- /dev/null
+++ b/analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/return_with_if.txt
@@ -0,0 +1,6 @@
+expression: IF
+text: if (n == 1)
+ return "one"
+ else
+ return "two"
+isUsedAsExpression: false