[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.
This commit is contained in:
Jaebaek Seo
2022-11-14 15:53:23 +00:00
committed by Ilya Kirillov
parent b6481ed891
commit c55efe62a3
13 changed files with 159 additions and 18 deletions
@@ -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 {
@@ -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 =
@@ -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 {
@@ -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 {
@@ -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 {
@@ -0,0 +1,5 @@
fun test(n: Int) =
<expr>if (n == 1)
"one"
else
"two"</expr>
@@ -0,0 +1,6 @@
expression: IF
text: if (n == 1)
"one"
else
"two"
isUsedAsExpression: true
@@ -0,0 +1,6 @@
fun test(n: Int) = {
<expr>if (n == 1)
"one"
else
"two"</expr>
}
@@ -0,0 +1,6 @@
expression: IF
text: if (n == 1)
"one"
else
"two"
isUsedAsExpression: true
@@ -0,0 +1,6 @@
fun test(n: Int): String {
if (n == 1)
<expr>return "one"</expr>
else
return "two"
}
@@ -0,0 +1,3 @@
expression: RETURN
text: return "one"
isUsedAsExpression: false
@@ -0,0 +1,6 @@
fun test(n: Int): String {
<expr>if (n == 1)
return "one"
else
return "two"</expr>
}
@@ -0,0 +1,6 @@
expression: IF
text: if (n == 1)
return "one"
else
return "two"
isUsedAsExpression: false