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 d4c73387c58..bc6fc1ff96e 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 @@ -958,6 +958,18 @@ public class Fe10IdeNormalAnalysisSourceModuleIsUsedAsExpressionTestGenerated ex runTest("analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/functionLiteralExtensionReceiverType.kt"); } + @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 { @@ -1510,12 +1522,24 @@ public class Fe10IdeNormalAnalysisSourceModuleIsUsedAsExpressionTestGenerated ex runTest("analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/return_implicit_unit.kt"); } + @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 { 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 de05b88e3d3..9f7d8bc8f8a 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 @@ internal class KtFirExpressionInfoProvider( 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 @@ private fun doesPropertyAccessorUseBody(propertyAccessor: KtPropertyAccessor, bo } /** - * 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 2f1ed276fd9..7d43c7c7c8f 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 @@ -958,6 +958,18 @@ public class FirIdeDependentAnalysisSourceModuleIsUsedAsExpressionTestGenerated runTest("analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/functionLiteralExtensionReceiverType.kt"); } + @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 { @@ -1510,12 +1522,24 @@ public class FirIdeDependentAnalysisSourceModuleIsUsedAsExpressionTestGenerated runTest("analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/return_implicit_unit.kt"); } + @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 { 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 936af657b40..94d5ad78b49 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 @@ -958,6 +958,18 @@ public class FirIdeNormalAnalysisSourceModuleIsUsedAsExpressionTestGenerated ext runTest("analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/functionLiteralExtensionReceiverType.kt"); } + @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 { @@ -1510,12 +1522,24 @@ public class FirIdeNormalAnalysisSourceModuleIsUsedAsExpressionTestGenerated ext runTest("analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/return_implicit_unit.kt"); } + @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 { 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 1970b25700f..66a462872e1 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 @@ -958,6 +958,18 @@ public class FirStandaloneNormalAnalysisSourceModuleIsUsedAsExpressionTestGenera runTest("analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/functionLiteralExtensionReceiverType.kt"); } + @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 { @@ -1510,12 +1522,24 @@ public class FirStandaloneNormalAnalysisSourceModuleIsUsedAsExpressionTestGenera runTest("analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/return_implicit_unit.kt"); } + @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 { 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 00000000000..3aa66292035 --- /dev/null +++ b/analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/function_body_with_if.kt @@ -0,0 +1,5 @@ +fun test(n: Int) = + if (n == 1) + "one" + else + "two" \ 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 00000000000..7618937d187 --- /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 00000000000..1eb5f326c05 --- /dev/null +++ b/analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/function_equal_block_with_if.kt @@ -0,0 +1,6 @@ +fun test(n: Int) = { + if (n == 1) + "one" + else + "two" +} \ 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 00000000000..7618937d187 --- /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 00000000000..ec7e387c332 --- /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) + return "one" + 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 00000000000..f5432371559 --- /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 00000000000..8217d961b73 --- /dev/null +++ b/analysis/analysis-api/testData/components/expressionInfoProvider/isUsedAsExpression/return_with_if.kt @@ -0,0 +1,6 @@ +fun test(n: Int): String { + if (n == 1) + return "one" + else + return "two" +} \ 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 00000000000..dc0fde42ce5 --- /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