KT-60341 [Analysis API] Provide a type for a FirNameReference only when it refers to an actual property/variable

We cannot always return null, because in such case some expressions
would become not fully explorable from the types perspective (see
the documentation on the `getCorrespondingTypeIfPossible`)

`FirNamedReference` might appear when resolving method references (like
`foo::bar`), but also when IJ Platform tries to resolve other parts of
the Kotlin PSI, notably a `KtNameReferenceExpression` in a
function call (`bar` in `foo.bar(baz)` expression).

N.B. FE10 implementation does not support returning `null` as a type -
currently it always returns `Unit` type in case it cannot figure out
the actual type. This issue should probably be tackled together with
KT-60166, so that both implementations are more or less aligned

^KT-60341 Fixed
^KT-59077 Fixed
^KTIJ-25745 Fixed
This commit is contained in:
Roman Golyshev
2023-06-03 00:21:17 +02:00
committed by teamcity
parent 19a60d6b85
commit b8052761db
66 changed files with 870 additions and 30 deletions
@@ -301,4 +301,146 @@ public class Fe10IdeNormalAnalysisSourceModuleHLExpressionTypeTestGenerated exte
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/assignment/readArrayElement.kt");
}
}
@Nested
@TestMetadata("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference")
@TestDataPath("$PROJECT_ROOT")
public class NameReference {
@Test
public void testAllFilesPresentInNameReference() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference"), Pattern.compile("^(.+)\\.kt$"), null, true);
}
@Test
@TestMetadata("assignment.kt")
public void testAssignment() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/assignment.kt");
}
@Test
@TestMetadata("assignment_qualified.kt")
public void testAssignment_qualified() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/assignment_qualified.kt");
}
@Test
@TestMetadata("callableReference.kt")
public void testCallableReference() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/callableReference.kt");
}
@Test
@TestMetadata("capturedBoundType.kt")
public void testCapturedBoundType() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/capturedBoundType.kt");
}
@Test
@TestMetadata("functionCall.kt")
public void testFunctionCall() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/functionCall.kt");
}
@Test
@TestMetadata("functionCall_invalid.kt")
public void testFunctionCall_invalid() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/functionCall_invalid.kt");
}
@Test
@TestMetadata("functionCall_safeAccess.kt")
public void testFunctionCall_safeAccess() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/functionCall_safeAccess.kt");
}
@Test
@TestMetadata("functionalType.kt")
public void testFunctionalType() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/functionalType.kt");
}
@Test
@TestMetadata("functionalType_parens_1.kt")
public void testFunctionalType_parens_1() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/functionalType_parens_1.kt");
}
@Test
@TestMetadata("functionalType_parens_2.kt")
public void testFunctionalType_parens_2() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/functionalType_parens_2.kt");
}
@Test
@TestMetadata("functionalType_withReceiver.kt")
public void testFunctionalType_withReceiver() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/functionalType_withReceiver.kt");
}
@Test
@TestMetadata("innerType_constructor.kt")
public void testInnerType_constructor() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/innerType_constructor.kt");
}
@Test
@TestMetadata("innerType_constructor_invalid.kt")
public void testInnerType_constructor_invalid() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/innerType_constructor_invalid.kt");
}
@Test
@TestMetadata("invokeCallOnObject1.kt")
public void testInvokeCallOnObject1() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/invokeCallOnObject1.kt");
}
@Test
@TestMetadata("invokeCallOnObject2.kt")
public void testInvokeCallOnObject2() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/invokeCallOnObject2.kt");
}
@Test
@TestMetadata("nestedType_constructor.kt")
public void testNestedType_constructor() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/nestedType_constructor.kt");
}
@Test
@TestMetadata("nestedType_constructor_invalid.kt")
public void testNestedType_constructor_invalid() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/nestedType_constructor_invalid.kt");
}
@Test
@TestMetadata("nestedType_object.kt")
public void testNestedType_object() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/nestedType_object.kt");
}
@Test
@TestMetadata("nestedType_object_extensionInvoke.kt")
public void testNestedType_object_extensionInvoke() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/nestedType_object_extensionInvoke.kt");
}
@Test
@TestMetadata("propertyCall.kt")
public void testPropertyCall() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/propertyCall.kt");
}
@Test
@TestMetadata("propertyCall_genericExtension.kt")
public void testPropertyCall_genericExtension() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/propertyCall_genericExtension.kt");
}
@Test
@TestMetadata("propertyCall_safeAccess.kt")
public void testPropertyCall_safeAccess() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/propertyCall_safeAccess.kt");
}
}
}
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.analysis.api.fir.components
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.analysis.api.components.KtExpressionTypeProvider
import org.jetbrains.kotlin.analysis.api.fir.KtFirAnalysisSession
import org.jetbrains.kotlin.analysis.api.fir.utils.getReferencedElementType
import org.jetbrains.kotlin.analysis.api.fir.utils.unwrap
import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken
import org.jetbrains.kotlin.analysis.api.types.KtErrorType
@@ -33,7 +32,7 @@ import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.utils.addToStdlib.applyIf
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.psi.psiUtil.getOutermostParenthesizerOrThis
internal class KtFirExpressionTypeProvider(
override val analysisSession: KtFirAnalysisSession,
@@ -71,7 +70,7 @@ internal class KtFirExpressionTypeProvider(
}
}
is FirExpression -> fir.typeRef.coneType.asKtType()
is FirNamedReference -> fir.getReferencedElementType().asKtType()
is FirNamedReference -> fir.getCorrespondingTypeIfPossible()?.asKtType()
is FirStatement -> with(analysisSession) { builtinTypes.UNIT }
is FirTypeRef, is FirImport, is FirPackageDirective, is FirLabel, is FirTypeParameterRef -> null
@@ -95,6 +94,49 @@ internal class KtFirExpressionTypeProvider(
}
}
/**
* It only makes sense to provide type for the references which reference some actual properties/variables.
*
* In cases when the name reference references a function (a REAL function, not a functional type variable), it does not
* make sense to provide any type for it.
*
* ---
*
* Why not just always provide null for name references? In such case, the following case would be a problem:
*
* ```kt
* fun usage(action: String.(Int) -> String) {
* "hello".<expr>action</expr>(10)
* }
* ```
*
* The user might want to know the type of the `action` callback. If we always return null for the named references,
* we won't be able to handle this request, and just return null. So the user will only be able to see the type
* of the whole expression instead, and that is not what he wants.
*/
private fun FirNamedReference.getCorrespondingTypeIfPossible(): ConeKotlinType? =
findOuterPropertyAccessExpression()?.typeRef?.coneType
/**
* Finds an outer expression for [this] named reference in cases when it is a part of a property access.
*
* Otherwise, return null.
*/
private fun FirNamedReference.findOuterPropertyAccessExpression(): FirExpression? {
val referenceExpression = psi as? KtExpression ?: return null
val outerExpression = referenceExpression.getOutermostParenthesizerOrThis().parent as? KtElement ?: return null
return when (val outerFirElement = outerExpression.getOrBuildFir(firResolveSession)) {
is FirVariableAssignment -> outerFirElement.lValue
is FirPropertyAccessExpression -> outerFirElement
is FirImplicitInvokeCall -> outerFirElement.explicitReceiver
is FirSafeCallExpression -> {
if (outerFirElement.selector is FirPropertyAccessExpression) outerFirElement else null
}
else -> null
}
}
private fun getReturnTypeForArrayStyleAssignmentTarget(
expression: KtExpression,
fir: FirFunctionCall
@@ -12,24 +12,16 @@ import org.jetbrains.kotlin.analysis.api.KtNonConstantInitializerValue
import org.jetbrains.kotlin.analysis.api.components.KtConstantEvaluationMode
import org.jetbrains.kotlin.analysis.api.fir.evaluate.FirAnnotationValueConverter
import org.jetbrains.kotlin.analysis.api.fir.evaluate.FirCompileTimeConstantEvaluator
import org.jetbrains.kotlin.analysis.api.fir.getCandidateSymbols
import org.jetbrains.kotlin.analysis.api.types.KtTypeNullability
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.checkers.classKind
import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClassSymbol
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.psi
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.references.FirNamedReference
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedNameError
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
import org.jetbrains.kotlin.fir.types.ConeErrorType
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.ConeNullability
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.*
@@ -50,18 +42,6 @@ internal fun KtExpression.unwrap(): KtExpression {
} ?: this
}
internal fun FirNamedReference.getReferencedElementType(): ConeKotlinType {
val symbols = when (this) {
is FirResolvedNamedReference -> listOf(resolvedSymbol)
is FirErrorNamedReference -> getCandidateSymbols()
else -> error("Unexpected ${this::class}")
}
val firCallableDeclaration = symbols.singleOrNull()?.fir as? FirCallableDeclaration
?: return ConeErrorType(ConeUnresolvedNameError(name))
return firCallableDeclaration.symbol.resolvedReturnType
}
internal fun KtTypeNullability.toConeNullability() = when (this) {
KtTypeNullability.NULLABLE -> ConeNullability.NULLABLE
KtTypeNullability.NON_NULLABLE -> ConeNullability.NOT_NULL
@@ -301,4 +301,146 @@ public class FirIdeDependentAnalysisSourceModuleHLExpressionTypeTestGenerated ex
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/assignment/readArrayElement.kt");
}
}
@Nested
@TestMetadata("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference")
@TestDataPath("$PROJECT_ROOT")
public class NameReference {
@Test
public void testAllFilesPresentInNameReference() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference"), Pattern.compile("^(.+)\\.kt$"), null, true);
}
@Test
@TestMetadata("assignment.kt")
public void testAssignment() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/assignment.kt");
}
@Test
@TestMetadata("assignment_qualified.kt")
public void testAssignment_qualified() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/assignment_qualified.kt");
}
@Test
@TestMetadata("callableReference.kt")
public void testCallableReference() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/callableReference.kt");
}
@Test
@TestMetadata("capturedBoundType.kt")
public void testCapturedBoundType() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/capturedBoundType.kt");
}
@Test
@TestMetadata("functionCall.kt")
public void testFunctionCall() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/functionCall.kt");
}
@Test
@TestMetadata("functionCall_invalid.kt")
public void testFunctionCall_invalid() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/functionCall_invalid.kt");
}
@Test
@TestMetadata("functionCall_safeAccess.kt")
public void testFunctionCall_safeAccess() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/functionCall_safeAccess.kt");
}
@Test
@TestMetadata("functionalType.kt")
public void testFunctionalType() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/functionalType.kt");
}
@Test
@TestMetadata("functionalType_parens_1.kt")
public void testFunctionalType_parens_1() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/functionalType_parens_1.kt");
}
@Test
@TestMetadata("functionalType_parens_2.kt")
public void testFunctionalType_parens_2() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/functionalType_parens_2.kt");
}
@Test
@TestMetadata("functionalType_withReceiver.kt")
public void testFunctionalType_withReceiver() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/functionalType_withReceiver.kt");
}
@Test
@TestMetadata("innerType_constructor.kt")
public void testInnerType_constructor() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/innerType_constructor.kt");
}
@Test
@TestMetadata("innerType_constructor_invalid.kt")
public void testInnerType_constructor_invalid() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/innerType_constructor_invalid.kt");
}
@Test
@TestMetadata("invokeCallOnObject1.kt")
public void testInvokeCallOnObject1() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/invokeCallOnObject1.kt");
}
@Test
@TestMetadata("invokeCallOnObject2.kt")
public void testInvokeCallOnObject2() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/invokeCallOnObject2.kt");
}
@Test
@TestMetadata("nestedType_constructor.kt")
public void testNestedType_constructor() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/nestedType_constructor.kt");
}
@Test
@TestMetadata("nestedType_constructor_invalid.kt")
public void testNestedType_constructor_invalid() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/nestedType_constructor_invalid.kt");
}
@Test
@TestMetadata("nestedType_object.kt")
public void testNestedType_object() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/nestedType_object.kt");
}
@Test
@TestMetadata("nestedType_object_extensionInvoke.kt")
public void testNestedType_object_extensionInvoke() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/nestedType_object_extensionInvoke.kt");
}
@Test
@TestMetadata("propertyCall.kt")
public void testPropertyCall() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/propertyCall.kt");
}
@Test
@TestMetadata("propertyCall_genericExtension.kt")
public void testPropertyCall_genericExtension() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/propertyCall_genericExtension.kt");
}
@Test
@TestMetadata("propertyCall_safeAccess.kt")
public void testPropertyCall_safeAccess() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/propertyCall_safeAccess.kt");
}
}
}
@@ -301,4 +301,146 @@ public class FirIdeNormalAnalysisSourceModuleHLExpressionTypeTestGenerated exten
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/assignment/readArrayElement.kt");
}
}
@Nested
@TestMetadata("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference")
@TestDataPath("$PROJECT_ROOT")
public class NameReference {
@Test
public void testAllFilesPresentInNameReference() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference"), Pattern.compile("^(.+)\\.kt$"), null, true);
}
@Test
@TestMetadata("assignment.kt")
public void testAssignment() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/assignment.kt");
}
@Test
@TestMetadata("assignment_qualified.kt")
public void testAssignment_qualified() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/assignment_qualified.kt");
}
@Test
@TestMetadata("callableReference.kt")
public void testCallableReference() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/callableReference.kt");
}
@Test
@TestMetadata("capturedBoundType.kt")
public void testCapturedBoundType() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/capturedBoundType.kt");
}
@Test
@TestMetadata("functionCall.kt")
public void testFunctionCall() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/functionCall.kt");
}
@Test
@TestMetadata("functionCall_invalid.kt")
public void testFunctionCall_invalid() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/functionCall_invalid.kt");
}
@Test
@TestMetadata("functionCall_safeAccess.kt")
public void testFunctionCall_safeAccess() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/functionCall_safeAccess.kt");
}
@Test
@TestMetadata("functionalType.kt")
public void testFunctionalType() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/functionalType.kt");
}
@Test
@TestMetadata("functionalType_parens_1.kt")
public void testFunctionalType_parens_1() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/functionalType_parens_1.kt");
}
@Test
@TestMetadata("functionalType_parens_2.kt")
public void testFunctionalType_parens_2() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/functionalType_parens_2.kt");
}
@Test
@TestMetadata("functionalType_withReceiver.kt")
public void testFunctionalType_withReceiver() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/functionalType_withReceiver.kt");
}
@Test
@TestMetadata("innerType_constructor.kt")
public void testInnerType_constructor() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/innerType_constructor.kt");
}
@Test
@TestMetadata("innerType_constructor_invalid.kt")
public void testInnerType_constructor_invalid() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/innerType_constructor_invalid.kt");
}
@Test
@TestMetadata("invokeCallOnObject1.kt")
public void testInvokeCallOnObject1() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/invokeCallOnObject1.kt");
}
@Test
@TestMetadata("invokeCallOnObject2.kt")
public void testInvokeCallOnObject2() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/invokeCallOnObject2.kt");
}
@Test
@TestMetadata("nestedType_constructor.kt")
public void testNestedType_constructor() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/nestedType_constructor.kt");
}
@Test
@TestMetadata("nestedType_constructor_invalid.kt")
public void testNestedType_constructor_invalid() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/nestedType_constructor_invalid.kt");
}
@Test
@TestMetadata("nestedType_object.kt")
public void testNestedType_object() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/nestedType_object.kt");
}
@Test
@TestMetadata("nestedType_object_extensionInvoke.kt")
public void testNestedType_object_extensionInvoke() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/nestedType_object_extensionInvoke.kt");
}
@Test
@TestMetadata("propertyCall.kt")
public void testPropertyCall() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/propertyCall.kt");
}
@Test
@TestMetadata("propertyCall_genericExtension.kt")
public void testPropertyCall_genericExtension() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/propertyCall_genericExtension.kt");
}
@Test
@TestMetadata("propertyCall_safeAccess.kt")
public void testPropertyCall_safeAccess() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/propertyCall_safeAccess.kt");
}
}
}
@@ -46,6 +46,12 @@ public class FirIdeDependentAnalysisSourceModuleAnalysisApiExpressionPsiTypeProv
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/components/psiTypeProvider/psiType/forExpression"), Pattern.compile("^(.+)\\.kt$"), null, true);
}
@Test
@TestMetadata("capturedBoundType.kt")
public void testCapturedBoundType() throws Exception {
runTest("analysis/analysis-api/testData/components/psiTypeProvider/psiType/forExpression/capturedBoundType.kt");
}
@Test
@TestMetadata("class_object_call.kt")
public void testClass_object_call() throws Exception {
@@ -58,6 +64,12 @@ public class FirIdeDependentAnalysisSourceModuleAnalysisApiExpressionPsiTypeProv
runTest("analysis/analysis-api/testData/components/psiTypeProvider/psiType/forExpression/class_object_constructor.kt");
}
@Test
@TestMetadata("KTIJ25461.kt")
public void testKTIJ25461() throws Exception {
runTest("analysis/analysis-api/testData/components/psiTypeProvider/psiType/forExpression/KTIJ25461.kt");
}
@Test
@TestMetadata("localClassWithUnresolvedSuperType.kt")
public void testLocalClassWithUnresolvedSuperType() throws Exception {
@@ -46,6 +46,12 @@ public class FirIdeNormalAnalysisSourceModuleAnalysisApiExpressionPsiTypeProvide
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/components/psiTypeProvider/psiType/forExpression"), Pattern.compile("^(.+)\\.kt$"), null, true);
}
@Test
@TestMetadata("capturedBoundType.kt")
public void testCapturedBoundType() throws Exception {
runTest("analysis/analysis-api/testData/components/psiTypeProvider/psiType/forExpression/capturedBoundType.kt");
}
@Test
@TestMetadata("class_object_call.kt")
public void testClass_object_call() throws Exception {
@@ -58,6 +64,12 @@ public class FirIdeNormalAnalysisSourceModuleAnalysisApiExpressionPsiTypeProvide
runTest("analysis/analysis-api/testData/components/psiTypeProvider/psiType/forExpression/class_object_constructor.kt");
}
@Test
@TestMetadata("KTIJ25461.kt")
public void testKTIJ25461() throws Exception {
runTest("analysis/analysis-api/testData/components/psiTypeProvider/psiType/forExpression/KTIJ25461.kt");
}
@Test
@TestMetadata("localClassWithUnresolvedSuperType.kt")
public void testLocalClassWithUnresolvedSuperType() throws Exception {
@@ -34,11 +34,14 @@ abstract class AbstractAnalysisApiExpressionPsiTypeProviderTest : AbstractAnalys
?: error("Can't find psi context for $containingDeclaration")
val actual = analyze(ktFile) {
val returnType = declarationAtCaret.getKtType()
?: error("Not a typable expression ${declarationAtCaret::class} ${declarationAtCaret.text}")
val psiType = returnType.asPsiType(psiContext, allowErrorTypes = false)
buildString {
appendLine("KtType: ${returnType.render(position = Variance.INVARIANT)}")
appendLine("PsiType: $psiType")
if (returnType != null) {
val psiType = returnType.asPsiType(psiContext, allowErrorTypes = false)
buildString {
appendLine("KtType: ${returnType.render(position = Variance.INVARIANT)}")
appendLine("PsiType: $psiType")
}
} else {
"null"
}
}
testServices.assertions.assertEqualsToTestDataFileSibling(actual)
@@ -301,4 +301,146 @@ public class FirStandaloneNormalAnalysisSourceModuleHLExpressionTypeTestGenerate
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/assignment/readArrayElement.kt");
}
}
@Nested
@TestMetadata("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference")
@TestDataPath("$PROJECT_ROOT")
public class NameReference {
@Test
public void testAllFilesPresentInNameReference() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference"), Pattern.compile("^(.+)\\.kt$"), null, true);
}
@Test
@TestMetadata("assignment.kt")
public void testAssignment() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/assignment.kt");
}
@Test
@TestMetadata("assignment_qualified.kt")
public void testAssignment_qualified() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/assignment_qualified.kt");
}
@Test
@TestMetadata("callableReference.kt")
public void testCallableReference() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/callableReference.kt");
}
@Test
@TestMetadata("capturedBoundType.kt")
public void testCapturedBoundType() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/capturedBoundType.kt");
}
@Test
@TestMetadata("functionCall.kt")
public void testFunctionCall() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/functionCall.kt");
}
@Test
@TestMetadata("functionCall_invalid.kt")
public void testFunctionCall_invalid() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/functionCall_invalid.kt");
}
@Test
@TestMetadata("functionCall_safeAccess.kt")
public void testFunctionCall_safeAccess() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/functionCall_safeAccess.kt");
}
@Test
@TestMetadata("functionalType.kt")
public void testFunctionalType() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/functionalType.kt");
}
@Test
@TestMetadata("functionalType_parens_1.kt")
public void testFunctionalType_parens_1() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/functionalType_parens_1.kt");
}
@Test
@TestMetadata("functionalType_parens_2.kt")
public void testFunctionalType_parens_2() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/functionalType_parens_2.kt");
}
@Test
@TestMetadata("functionalType_withReceiver.kt")
public void testFunctionalType_withReceiver() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/functionalType_withReceiver.kt");
}
@Test
@TestMetadata("innerType_constructor.kt")
public void testInnerType_constructor() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/innerType_constructor.kt");
}
@Test
@TestMetadata("innerType_constructor_invalid.kt")
public void testInnerType_constructor_invalid() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/innerType_constructor_invalid.kt");
}
@Test
@TestMetadata("invokeCallOnObject1.kt")
public void testInvokeCallOnObject1() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/invokeCallOnObject1.kt");
}
@Test
@TestMetadata("invokeCallOnObject2.kt")
public void testInvokeCallOnObject2() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/invokeCallOnObject2.kt");
}
@Test
@TestMetadata("nestedType_constructor.kt")
public void testNestedType_constructor() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/nestedType_constructor.kt");
}
@Test
@TestMetadata("nestedType_constructor_invalid.kt")
public void testNestedType_constructor_invalid() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/nestedType_constructor_invalid.kt");
}
@Test
@TestMetadata("nestedType_object.kt")
public void testNestedType_object() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/nestedType_object.kt");
}
@Test
@TestMetadata("nestedType_object_extensionInvoke.kt")
public void testNestedType_object_extensionInvoke() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/nestedType_object_extensionInvoke.kt");
}
@Test
@TestMetadata("propertyCall.kt")
public void testPropertyCall() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/propertyCall.kt");
}
@Test
@TestMetadata("propertyCall_genericExtension.kt")
public void testPropertyCall_genericExtension() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/propertyCall_genericExtension.kt");
}
@Test
@TestMetadata("propertyCall_safeAccess.kt")
public void testPropertyCall_safeAccess() throws Exception {
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference/propertyCall_safeAccess.kt");
}
}
}
@@ -46,6 +46,12 @@ public class FirStandaloneNormalAnalysisSourceModuleAnalysisApiExpressionPsiType
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/components/psiTypeProvider/psiType/forExpression"), Pattern.compile("^(.+)\\.kt$"), null, true);
}
@Test
@TestMetadata("capturedBoundType.kt")
public void testCapturedBoundType() throws Exception {
runTest("analysis/analysis-api/testData/components/psiTypeProvider/psiType/forExpression/capturedBoundType.kt");
}
@Test
@TestMetadata("class_object_call.kt")
public void testClass_object_call() throws Exception {
@@ -58,6 +64,12 @@ public class FirStandaloneNormalAnalysisSourceModuleAnalysisApiExpressionPsiType
runTest("analysis/analysis-api/testData/components/psiTypeProvider/psiType/forExpression/class_object_constructor.kt");
}
@Test
@TestMetadata("KTIJ25461.kt")
public void testKTIJ25461() throws Exception {
runTest("analysis/analysis-api/testData/components/psiTypeProvider/psiType/forExpression/KTIJ25461.kt");
}
@Test
@TestMetadata("localClassWithUnresolvedSuperType.kt")
public void testLocalClassWithUnresolvedSuperType() throws Exception {
@@ -0,0 +1,5 @@
fun test() {
val foo = 10
<expr>foo</expr> = 20
}
@@ -0,0 +1,2 @@
expression: foo
type: kotlin.Int
@@ -0,0 +1,6 @@
class Foo {
var bar: Int = 0
}
fun test(foo: Foo) {
foo.<expr>bar</expr> = 20
}
@@ -0,0 +1,2 @@
expression: bar
type: kotlin.Int
@@ -0,0 +1,2 @@
expression: myFun
type: kotlin.Unit
@@ -0,0 +1,5 @@
fun myFun(i: Int): String = i.toString()
fun test() {
::<expr>myFun</expr>
}
@@ -0,0 +1,2 @@
expression: myFun
type: null
@@ -0,0 +1,2 @@
expression: functionWithGeneric
type: kotlin.Unit
@@ -0,0 +1,10 @@
interface WithGeneric<S> {
fun <T : S> functionWithGeneric(t: T): T
fun prop(): S
}
fun take(w: WithGeneric<*>) {
// this is an error on purpose!
w.<expr>functionWithGeneric</expr>
}
@@ -0,0 +1,2 @@
expression: functionWithGeneric
type: ERROR(Cannot infer argument for type parameter T)
@@ -0,0 +1,2 @@
expression: foo
type: kotlin.Unit
@@ -0,0 +1,5 @@
fun String.foo(i: Int): String = ""
fun take(s: String) {
s.<expr>foo</expr>(10)
}
@@ -0,0 +1,2 @@
expression: foo
type: null
@@ -0,0 +1,5 @@
fun String.foo(i: Int): String = ""
fun take(s: String) {
s.<expr>foo</expr>
}
@@ -0,0 +1,2 @@
expression: foo
type: kotlin.String
@@ -0,0 +1,5 @@
fun String.foo(i: Int): String = ""
fun take(s: String?) {
s?.<expr>foo</expr>(10)
}
@@ -0,0 +1,3 @@
fun take(lambda: (Int) -> String) {
<expr>lambda</expr>(10)
}
@@ -0,0 +1,2 @@
expression: lambda
type: (kotlin.Int) -> kotlin.String
@@ -0,0 +1,3 @@
fun take(lambda: (Int) -> String) {
(<expr>lambda</expr>)(10)
}
@@ -0,0 +1,2 @@
expression: lambda
type: (kotlin.Int) -> kotlin.String
@@ -0,0 +1,3 @@
fun take(lambda: (Int) -> String) {
<expr>(lambda)</expr>(10)
}
@@ -0,0 +1,2 @@
expression: (lambda)
type: (kotlin.Int) -> kotlin.String
@@ -0,0 +1,3 @@
fun take(lambda: String.(Int) -> String) {
"hello".<expr>lambda</expr>(10)
}
@@ -0,0 +1,2 @@
expression: lambda
type: kotlin.String.(kotlin.Int) -> kotlin.String
@@ -0,0 +1,7 @@
class Foo {
inner class Bar
}
fun foo(foo: Foo) {
foo.<expr>Bar</expr>()
}
@@ -0,0 +1,7 @@
class Foo {
inner class Bar
}
fun foo(foo: Foo) {
foo.<expr>Bar</expr>
}
@@ -0,0 +1,7 @@
object Foo {
operator fun invoke(i: Int): String {}
}
fun take() {
<expr>Foo</expr>(10)
}
@@ -0,0 +1,9 @@
class Foo {
companion object {
operator fun invoke(i: Int): String {}
}
}
fun take() {
<expr>Foo</expr>(10)
}
@@ -0,0 +1,2 @@
expression: Foo
type: Foo.Companion
@@ -0,0 +1,7 @@
class Foo {
class Bar
}
fun foo() {
Foo.<expr>Bar</expr>()
}
@@ -0,0 +1,7 @@
class Foo {
class Bar
}
fun foo() {
Foo.<expr>Bar</expr>
}
@@ -0,0 +1,2 @@
expression: Bar
type: kotlin.Unit
@@ -0,0 +1,7 @@
class Foo {
object Bar
}
fun foo() {
Foo.<expr>Bar</expr>
}
@@ -0,0 +1,2 @@
expression: Bar
type: Foo.Bar
@@ -0,0 +1,9 @@
class Foo {
object Bar
}
operator fun Bar.invoke() {}
fun foo() {
Foo.<expr>Bar</expr>()
}
@@ -0,0 +1,5 @@
val String.foo: String get() = ""
fun take(s: String) {
s.<expr>foo</expr>
}
@@ -0,0 +1,2 @@
expression: foo
type: kotlin.String
@@ -0,0 +1,11 @@
interface WithGeneric<T>
interface Foo<T> {
val foo: WithGeneric<T>
}
val <T> Foo<T>.fooExt: WithGeneric<T> get() = foo
fun take(s: Foo<String>) {
s.<expr>fooExt</expr>
}
@@ -0,0 +1,2 @@
expression: fooExt
type: WithGeneric<kotlin.String>
@@ -0,0 +1,5 @@
val String.foo: String get() = ""
fun take(s: String?) {
s?.<expr>foo</expr>
}
@@ -0,0 +1,2 @@
expression: foo
type: kotlin.String?
@@ -0,0 +1,7 @@
interface BodySpec<B, S : BodySpec<B, S>> {
fun <T : S> isEqualTo(expected: B) : T
}
fun test(b: BodySpec<String, *>) {
b.<expr>isEqualTo</expr>("")
}
@@ -0,0 +1,10 @@
interface WithGeneric<S> {
fun <T : S> functionWithGeneric(t: T): T
fun prop(): S
}
fun take(w: WithGeneric<*>) {
// this is an error on purpose!
w.<expr>functionWithGeneric</expr>
}
@@ -0,0 +1,2 @@
KtType: T
PsiType: null
@@ -1,2 +1 @@
KtType: T & kotlin.Any
PsiType: PsiType:T
null