Analysis API: fix getKtExpressionType for array assignment target

This commit is contained in:
Ilya Kirillov
2021-12-31 12:57:56 +03:00
parent a5ebd3c716
commit af789346f5
12 changed files with 100 additions and 1 deletions
@@ -209,4 +209,32 @@ public class KtFe10HLExpressionTypeTestGenerated extends AbstractKtFe10HLExpress
public void testWhileExpression() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/whileExpression.kt");
}
@Nested
@TestMetadata("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/assignment")
@TestDataPath("$PROJECT_ROOT")
public class Assignment {
@Test
public void testAllFilesPresentInAssignment() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/assignment"), Pattern.compile("^(.+)\\.kt$"), null, true);
}
@Test
@TestMetadata("arrayAssignementTarget.kt")
public void testArrayAssignementTarget() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/assignment/arrayAssignementTarget.kt");
}
@Test
@TestMetadata("arrayAssignmentTargetUnresovledSet.kt")
public void testArrayAssignmentTargetUnresovledSet() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/assignment/arrayAssignmentTargetUnresovledSet.kt");
}
@Test
@TestMetadata("arrayCompoundAssignementTarget.kt")
public void testArrayCompoundAssignementTarget() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/assignment/arrayCompoundAssignementTarget.kt");
}
}
}
@@ -39,6 +39,10 @@ internal class KtFirExpressionTypeProvider(
override fun getKtExpressionType(expression: KtExpression): KtType? = withValidityAssertion {
when (val fir = expression.unwrap().getOrBuildFir(firResolveState)) {
is FirFunctionCall -> {
getReturnTypeForArrayStyleAssignmentTarget(expression, fir)
?: fir.typeRef.coneType.asKtType()
}
is FirPropertyAccessExpression -> {
// For unresolved `super`, we manually create an intersection type so that IDE features like completion can work correctly.
val containingClass =
@@ -78,6 +82,18 @@ internal class KtFirExpressionTypeProvider(
}
}
private fun getReturnTypeForArrayStyleAssignmentTarget(
expression: KtExpression,
fir: FirFunctionCall
): KtType? {
if (fir.calleeReference !is FirResolvedNamedReference) return null
if (expression !is KtArrayAccessExpression) return null
val assignment = expression.parent as? KtBinaryExpression ?: return null
if (assignment.operationToken !in KtTokens.ALL_ASSIGNMENTS) return null
val setTargetArgumentParameter = fir.argumentMapping?.entries?.last()?.value ?: return null
return setTargetArgumentParameter.returnTypeRef.coneType.asKtType()
}
override fun getReturnTypeForKtDeclaration(declaration: KtDeclaration): KtType = withValidityAssertion {
val firDeclaration = declaration.getOrBuildFirOfType<FirCallableDeclaration>(firResolveState)
firDeclaration.returnTypeRef.coneType.asKtType()
@@ -209,4 +209,32 @@ public class FirHLExpressionTypeTestGenerated extends AbstractFirHLExpressionTyp
public void testWhileExpression() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/whileExpression.kt");
}
@Nested
@TestMetadata("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/assignment")
@TestDataPath("$PROJECT_ROOT")
public class Assignment {
@Test
public void testAllFilesPresentInAssignment() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/assignment"), Pattern.compile("^(.+)\\.kt$"), null, true);
}
@Test
@TestMetadata("arrayAssignementTarget.kt")
public void testArrayAssignementTarget() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/assignment/arrayAssignementTarget.kt");
}
@Test
@TestMetadata("arrayAssignmentTargetUnresovledSet.kt")
public void testArrayAssignmentTargetUnresovledSet() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/assignment/arrayAssignmentTargetUnresovledSet.kt");
}
@Test
@TestMetadata("arrayCompoundAssignementTarget.kt")
public void testArrayCompoundAssignementTarget() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/assignment/arrayCompoundAssignementTarget.kt");
}
}
}
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.analysis.api.impl.base.test.components.expressionTypeProvider
import org.jetbrains.kotlin.analysis.api.components.KtTypeRendererOptions
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.FrontendApiTestConfiguratorService
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.expressionMarkerProvider
import org.jetbrains.kotlin.analysis.api.impl.base.test.test.framework.AbstractHLApiSingleFileTest
@@ -24,7 +25,7 @@ abstract class AbstractHLExpressionTypeTest(configurator: FrontendApiTestConfigu
else -> null
} ?: error("expect an expression but got ${selected.text}")
val type = executeOnPooledThreadInReadAction {
analyseForTest(expression) { expression.getKtType()?.render() }
analyseForTest(expression) { expression.getKtType()?.render(TYPE_RENDERING_OPTIONS) }
}
val actual = buildString {
appendLine("expression: ${expression.text}")
@@ -32,4 +33,8 @@ abstract class AbstractHLExpressionTypeTest(configurator: FrontendApiTestConfigu
}
testServices.assertions.assertEqualsToTestDataFileSibling(actual)
}
companion object {
private val TYPE_RENDERING_OPTIONS = KtTypeRendererOptions.DEFAULT.copy(renderUnresolvedTypeAsResolved = false)
}
}
@@ -0,0 +1,2 @@
expression: arr[0]
type: kotlin.Unit
@@ -0,0 +1,4 @@
fun foo() {
val arr = arrayOfNulls<List<*>>(10)
<expr>arr[0]</expr> = emptyList<Any>()
}
@@ -0,0 +1,2 @@
expression: arr[0]
type: kotlin.collections.List<*>?
@@ -0,0 +1,4 @@
fun foo() {
val arr = 1
<expr>arr[0]</expr> = 1
}
@@ -0,0 +1,2 @@
expression: arr[0]
type: ERROR_TYPE <Unresolved name: set>
@@ -0,0 +1,4 @@
fun foo() {
val arr = intArrayOf()
<expr>arr[0]</expr> += 1
}
@@ -0,0 +1,2 @@
expression: arr[0]
type: kotlin.Int