FIR IDE/UAST: get PsiType from KtTypeReference

This commit is contained in:
Jinseong Jeon
2021-06-01 10:59:07 -07:00
committed by teamcityserver
parent a3710bed6a
commit 47ede5bdc8
21 changed files with 175 additions and 26 deletions
@@ -1660,6 +1660,10 @@ fun main(args: Array<String>) {
testClass<AbstractFirUastDeclarationTest> {
model("declaration")
}
testClass<AbstractFirUastTypesTest> {
model("type")
}
}
testGroup("plugins/uast-kotlin-fir/tests", "plugins/uast-kotlin/testData") {
@@ -1684,6 +1688,10 @@ fun main(args: Array<String>) {
testClass<AbstractFE1UastDeclarationTest> {
model("declaration")
}
testClass<AbstractFE1UastTypesTest> {
model("type")
}
}
testGroup("plugins/uast-kotlin-fir/tests", "plugins/uast-kotlin/testData") {
+1
View File
@@ -9,6 +9,7 @@ dependencies {
compileOnly(project(":compiler:psi"))
compileOnly(project(":compiler:frontend"))
compileOnly(project(":core:compiler.common"))
compileOnly(project(":core:compiler.common.jvm"))
compileOnly(project(":idea:idea-frontend-independent"))
compileOnly(intellijCoreDep())
compileOnly(intellijDep())
@@ -5,10 +5,13 @@
package org.jetbrains.kotlin.idea.frontend.api.components
import com.intellij.psi.PsiType
import org.jetbrains.kotlin.idea.frontend.api.ValidityTokenOwner
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtNamedClassOrObjectSymbol
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
import org.jetbrains.kotlin.idea.frontend.api.types.KtTypeNullability
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
import org.jetbrains.kotlin.psi.KtTypeReference
abstract class KtTypeProvider : KtAnalysisSessionComponent() {
abstract val builtinTypes: KtBuiltinTypes
@@ -17,6 +20,8 @@ abstract class KtTypeProvider : KtAnalysisSessionComponent() {
abstract fun buildSelfClassType(symbol: KtNamedClassOrObjectSymbol): KtType
abstract fun getPsiType(ktTypeReference: KtTypeReference, mode: TypeMappingMode): PsiType
abstract fun withNullability(type: KtType, newNullability: KtTypeNullability): KtType
}
@@ -36,6 +41,9 @@ interface KtTypeProviderMixIn : KtAnalysisSessionMixIn {
fun KtNamedClassOrObjectSymbol.buildSelfClassType(): KtType =
analysisSession.typeProvider.buildSelfClassType(this)
fun KtTypeReference.getPsiType(mode: TypeMappingMode = TypeMappingMode.DEFAULT): PsiType =
analysisSession.typeProvider.getPsiType(this, mode)
fun KtType.withNullability(newNullability: KtTypeNullability): KtType =
analysisSession.typeProvider.withNullability(this, newNullability)
}
@@ -60,4 +68,4 @@ abstract class KtBuiltinTypes : ValidityTokenOwner {
abstract val NULLABLE_ANY: KtType
abstract val NULLABLE_NOTHING: KtType
}
}
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.idea.frontend.api.fir.components
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnostic
@@ -14,9 +15,11 @@ import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.ConeTypeCheckerContext
import org.jetbrains.kotlin.idea.asJava.asPsiType
import org.jetbrains.kotlin.idea.frontend.api.diagnostics.KtDiagnosticWithPsi
import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession
import org.jetbrains.kotlin.idea.frontend.api.fir.diagnostics.KT_DIAGNOSTIC_CONVERTER
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
internal interface KtFirAnalysisSessionComponent {
val analysisSession: KtFirAnalysisSession
@@ -27,6 +30,9 @@ internal interface KtFirAnalysisSessionComponent {
fun ConeKotlinType.asKtType() = analysisSession.firSymbolBuilder.typeBuilder.buildKtType(this)
fun ConeKotlinType.asPsiType(mode: TypeMappingMode, psiContext: PsiElement) =
asPsiType(rootModuleSession, analysisSession.firResolveState, mode, psiContext)
fun FirPsiDiagnostic<*>.asKtDiagnostic(): KtDiagnosticWithPsi<*> =
KT_DIAGNOSTIC_CONVERTER.convert(analysisSession, this as FirDiagnostic<*>)
@@ -18,7 +18,6 @@ import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.types.ConeClassErrorType
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.idea.asJava.asPsiType
import org.jetbrains.kotlin.idea.fir.low.level.api.api.getOrBuildFir
import org.jetbrains.kotlin.idea.fir.low.level.api.api.getOrBuildFirOfType
import org.jetbrains.kotlin.idea.fir.low.level.api.api.getOrBuildFirSafe
@@ -63,9 +62,6 @@ internal class KtFirExpressionTypeProvider(
}
}
private fun ConeKotlinType.asPsiType(mode: TypeMappingMode, psiContext: PsiElement) =
asPsiType(rootModuleSession, analysisSession.firResolveState, mode, psiContext)
private fun FirNamedReference.getReferencedElementType(): ConeKotlinType {
val symbols = when (this) {
is FirResolvedNamedReference -> listOf(resolvedSymbol)
@@ -5,11 +5,15 @@
package org.jetbrains.kotlin.idea.frontend.api.fir.components
import com.intellij.psi.PsiType
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
import org.jetbrains.kotlin.fir.types.withNullability
import org.jetbrains.kotlin.idea.fir.low.level.api.api.getOrBuildFir
import org.jetbrains.kotlin.idea.frontend.api.components.KtBuiltinTypes
import org.jetbrains.kotlin.idea.frontend.api.components.KtTypeProvider
import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession
@@ -21,6 +25,9 @@ import org.jetbrains.kotlin.idea.frontend.api.symbols.KtNamedClassOrObjectSymbol
import org.jetbrains.kotlin.idea.frontend.api.tokens.ValidityToken
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
import org.jetbrains.kotlin.idea.frontend.api.types.KtTypeNullability
import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
import org.jetbrains.kotlin.psi.KtTypeReference
internal class KtFirTypeProvider(
override val analysisSession: KtFirAnalysisSession,
@@ -39,7 +46,6 @@ internal class KtFirTypeProvider(
return approximatedConeType?.asKtType()
}
override fun buildSelfClassType(symbol: KtNamedClassOrObjectSymbol): KtType {
require(symbol is KtFirNamedClassOrObjectSymbol)
val type = symbol.firRef.withFir(FirResolvePhase.SUPER_TYPES) { firClass ->
@@ -52,6 +58,14 @@ internal class KtFirTypeProvider(
return type.asKtType()
}
override fun getPsiType(ktTypeReference: KtTypeReference, mode: TypeMappingMode): PsiType = withValidityAssertion {
when (val fir = ktTypeReference.getOrBuildFir(firResolveState)) {
// NB: [FirErrorTypeRef] is a subtype of [FirResolvedTypeRef], and the error type in it will be properly handled by [asPsiType].
is FirResolvedTypeRef -> fir.coneType.asPsiType(mode, ktTypeReference)
else -> error("Unexpected ${fir::class}")
}
}
override fun withNullability(type: KtType, newNullability: KtTypeNullability): KtType {
require(type is KtFirType)
return type.coneType.withNullability(newNullability.toConeNullability(), rootModuleSession.typeContext).asKtType()
@@ -38,8 +38,9 @@ interface FirKotlinUastResolveProviderService : BaseKotlinUastResolveProviderSer
}
override fun resolveToType(ktTypeReference: KtTypeReference, source: UElement): PsiType? {
// TODO: use type conversions in firLightUtils.kt
return PsiType.NULL
analyseWithCustomToken(ktTypeReference, AlwaysAccessibleValidityTokenFactory) {
return ktTypeReference.getPsiType(TypeMappingMode.DEFAULT_UAST)
}
}
override fun getExpressionType(uExpression: UExpression): PsiType? {
@@ -8,7 +8,7 @@ public abstract interface Base {
public abstract fun print() : void = UastEmptyExpression
}
public final class BaseImpl : null {
public final class BaseImpl : Base {
private final var x: int
public fun BaseImpl(x: int) = UastEmptyExpression
public final fun getX() : int = UastEmptyExpression
@@ -17,6 +17,6 @@ public final class BaseImpl : null {
}
}
public final class Derived : null, null {
public final class Derived : Base, java.lang.CharSequence {
public fun Derived(b: Base) = UastEmptyExpression
}
@@ -4,6 +4,6 @@ public abstract interface Foo {
}
}
public final class Baz : null {
public final class Baz : Foo {
public fun Baz() = UastEmptyExpression
}
@@ -14,11 +14,11 @@ public class A {
}
}
public final class B : null {
public final class B : A {
public fun B(param: java.lang.String) = UastEmptyExpression
}
public final class C : null {
public final class C : A {
public fun C(p: java.lang.String) = UastEmptyExpression
public fun C(i: int) {
[!] UnknownKotlinExpression (CALL_EXPRESSION)
@@ -28,7 +28,7 @@ public final class C : null {
}
}
public final class O : null {
public final class O : A {
public static final var INSTANCE: O
private fun O() = UastEmptyExpression
}
@@ -7,7 +7,7 @@ UFile (package = ) [public final class ConstructorDelegateKt {...]
[!] UnknownKotlinExpression (CALL_EXPRESSION) [[!] UnknownKotlinExpression (CALL_EXPRESSION)]
UClass (name = Base) [public abstract interface Base {...}]
UMethod (name = print) [public abstract fun print() : void = UastEmptyExpression]
UClass (name = BaseImpl) [public final class BaseImpl : null {...}]
UClass (name = BaseImpl) [public final class BaseImpl : Base {...}]
UField (name = x) [private final var x: int]
UMethod (name = BaseImpl) [public fun BaseImpl(x: int) = UastEmptyExpression]
UParameter (name = x) [var x: int]
@@ -15,6 +15,6 @@ UFile (package = ) [public final class ConstructorDelegateKt {...]
UMethod (name = print) [public fun print() : void {...}]
UBlockExpression [{...}] : PsiType:Unit
[!] UnknownKotlinExpression (CALL_EXPRESSION) [[!] UnknownKotlinExpression (CALL_EXPRESSION)]
UClass (name = Derived) [public final class Derived : null, null {...}]
UClass (name = Derived) [public final class Derived : Base, java.lang.CharSequence {...}]
UMethod (name = Derived) [public fun Derived(b: Base) = UastEmptyExpression]
UParameter (name = b) [var b: Base]
@@ -4,5 +4,5 @@ UFile (package = ) [public abstract interface Foo {...]
UBlockExpression [{...}]
UReturnExpression [return "Hello!"]
ULiteralExpression (value = "Hello!") ["Hello!"] : PsiType:String
UClass (name = Baz) [public final class Baz : null {...}]
UClass (name = Baz) [public final class Baz : Foo {...}]
UMethod (name = Baz) [public fun Baz() = UastEmptyExpression]
@@ -16,10 +16,10 @@ UFile (package = ) [public final class SuperCallsKt {...]
UMethod (name = foo) [public fun foo(a: long) : void {...}]
UParameter (name = a) [var a: long]
UBlockExpression [{...}] : PsiType:Unit
UClass (name = B) [public final class B : null {...}]
UClass (name = B) [public final class B : A {...}]
UMethod (name = B) [public fun B(param: java.lang.String) = UastEmptyExpression]
UParameter (name = param) [var param: java.lang.String]
UClass (name = C) [public final class C : null {...}]
UClass (name = C) [public final class C : A {...}]
UMethod (name = C) [public fun C(p: java.lang.String) = UastEmptyExpression]
UParameter (name = p) [var p: java.lang.String]
UMethod (name = C) [public fun C(i: int) {...}]
@@ -30,6 +30,6 @@ UFile (package = ) [public final class SuperCallsKt {...]
UParameter (name = a) [var a: long]
UBlockExpression [{...}] : PsiType:Unit
[!] UnknownKotlinExpression (DOT_QUALIFIED_EXPRESSION) [[!] UnknownKotlinExpression (DOT_QUALIFIED_EXPRESSION)]
UClass (name = O) [public final class O : null {...}]
UClass (name = O) [public final class O : A {...}]
UField (name = INSTANCE) [public static final var INSTANCE: O]
UMethod (name = O) [private fun O() = UastEmptyExpression]
@@ -7,7 +7,7 @@ UFile (package = ) [public final class ConstructorDelegateKt {...]
[!] UnknownKotlinExpression (CALL_EXPRESSION) [[!] UnknownKotlinExpression (CALL_EXPRESSION)] = Undetermined
UClass (name = Base) [public abstract interface Base {...}]
UMethod (name = print) [public abstract fun print() : void = UastEmptyExpression]
UClass (name = BaseImpl) [public final class BaseImpl : null {...}]
UClass (name = BaseImpl) [public final class BaseImpl : Base {...}]
UField (name = x) [private final var x: int]
UMethod (name = BaseImpl) [public fun BaseImpl(x: int) = UastEmptyExpression]
UParameter (name = x) [var x: int]
@@ -15,6 +15,6 @@ UFile (package = ) [public final class ConstructorDelegateKt {...]
UMethod (name = print) [public fun print() : void {...}]
UBlockExpression [{...}] = Undetermined
[!] UnknownKotlinExpression (CALL_EXPRESSION) [[!] UnknownKotlinExpression (CALL_EXPRESSION)] = Undetermined
UClass (name = Derived) [public final class Derived : null, null {...}]
UClass (name = Derived) [public final class Derived : Base, java.lang.CharSequence {...}]
UMethod (name = Derived) [public fun Derived(b: Base) = UastEmptyExpression]
UParameter (name = b) [var b: Base]
@@ -4,5 +4,5 @@ UFile (package = ) [public abstract interface Foo {...]
UBlockExpression [{...}] = Nothing
UReturnExpression [return "Hello!"] = Nothing
ULiteralExpression (value = "Hello!") ["Hello!"] = "Hello!"
UClass (name = Baz) [public final class Baz : null {...}]
UClass (name = Baz) [public final class Baz : Foo {...}]
UMethod (name = Baz) [public fun Baz() = UastEmptyExpression]
@@ -16,10 +16,10 @@ UFile (package = ) [public final class SuperCallsKt {...]
UMethod (name = foo) [public fun foo(a: long) : void {...}]
UParameter (name = a) [var a: long]
UBlockExpression [{...}] = Undetermined
UClass (name = B) [public final class B : null {...}]
UClass (name = B) [public final class B : A {...}]
UMethod (name = B) [public fun B(param: java.lang.String) = UastEmptyExpression]
UParameter (name = param) [var param: java.lang.String]
UClass (name = C) [public final class C : null {...}]
UClass (name = C) [public final class C : A {...}]
UMethod (name = C) [public fun C(p: java.lang.String) = UastEmptyExpression]
UParameter (name = p) [var p: java.lang.String]
UMethod (name = C) [public fun C(i: int) {...}]
@@ -30,6 +30,6 @@ UFile (package = ) [public final class SuperCallsKt {...]
UParameter (name = a) [var a: long]
UBlockExpression [{...}] = Undetermined
[!] UnknownKotlinExpression (DOT_QUALIFIED_EXPRESSION) [[!] UnknownKotlinExpression (DOT_QUALIFIED_EXPRESSION)] = Undetermined
UClass (name = O) [public final class O : null {...}]
UClass (name = O) [public final class O : A {...}]
UField (name = INSTANCE) [public static final var INSTANCE: O]
UMethod (name = O) [private fun O() = UastEmptyExpression]
+11
View File
@@ -0,0 +1,11 @@
fun foo(x: Unresolved) {
}
class A(
val prop: Unresolved
) : UnresolvedBase(prop) {
override fun bar() : UnresolvedBase {
}
}
@@ -0,0 +1,20 @@
UFile (package = ) [public final class UnresolvedKt {...]
UClass (name = UnresolvedKt) [public final class UnresolvedKt {...}]
UMethod (name = foo) [public static final fun foo(@org.jetbrains.annotations.NotNull x: error.NonExistentClass) : void {...}]
UParameter (name = x) [@org.jetbrains.annotations.NotNull var x: error.NonExistentClass]
UAnnotation (fqName = org.jetbrains.annotations.NotNull) [@org.jetbrains.annotations.NotNull]
UBlockExpression [{...}] : PsiType:void
UClass (name = A) [public final class A : <ErrorType> {...}]
UField (name = prop) [@org.jetbrains.annotations.NotNull private final var prop: error.NonExistentClass]
UAnnotation (fqName = org.jetbrains.annotations.NotNull) [@org.jetbrains.annotations.NotNull]
UMethod (name = bar) [public fun bar() : error.NonExistentClass {...}]
UBlockExpression [{...}] : PsiType:void
UMethod (name = getProp) [public final fun getProp() : error.NonExistentClass = UastEmptyExpression]
UMethod (name = A) [public fun A(@org.jetbrains.annotations.NotNull prop: error.NonExistentClass) {...}]
UParameter (name = prop) [@org.jetbrains.annotations.NotNull var prop: error.NonExistentClass]
UAnnotation (fqName = org.jetbrains.annotations.NotNull) [@org.jetbrains.annotations.NotNull]
UBlockExpression [{...}]
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1)) [<anonymous class>(prop)]
UIdentifier (Identifier (UnresolvedBase)) [UIdentifier (Identifier (UnresolvedBase))]
USimpleNameReferenceExpression (identifier = <anonymous class>, resolvesTo = null) [<anonymous class>]
USimpleNameReferenceExpression (identifier = prop) [prop] : PsiType:<ErrorType>
@@ -0,0 +1,12 @@
UFile (package = ) [public final class UnresolvedKt {...]
UClass (name = UnresolvedKt) [public final class UnresolvedKt {...}]
UMethod (name = foo) [public static final fun foo(x: error.NonExistentClass) : void {...}]
UParameter (name = x) [var x: error.NonExistentClass]
UBlockExpression [{...}] : PsiType:Unit
UClass (name = A) [public final class A : error.NonExistentClass {...}]
UField (name = prop) [private final var prop: error.NonExistentClass]
UMethod (name = A) [public fun A(prop: error.NonExistentClass) = UastEmptyExpression]
UParameter (name = prop) [var prop: error.NonExistentClass]
UMethod (name = getProp) [public final fun getProp() : error.NonExistentClass = UastEmptyExpression]
UMethod (name = bar) [public fun bar() : error.NonExistentClass {...}]
UBlockExpression [{...}] : PsiType:Unit
@@ -0,0 +1,36 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.uast.test.kotlin;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.util.KtTestUtil;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("plugins/uast-kotlin-fir/testData/type")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class FE1UastTypesTestGenerated extends AbstractFE1UastTypesTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInType() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/uast-kotlin-fir/testData/type"), Pattern.compile("^(.+)\\.kt$"), null, true);
}
@TestMetadata("unresolved.kt")
public void testUnresolved() throws Exception {
runTest("plugins/uast-kotlin-fir/testData/type/unresolved.kt");
}
}
@@ -0,0 +1,36 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.uast.test.kotlin;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.util.KtTestUtil;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("plugins/uast-kotlin-fir/testData/type")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class FirUastTypesTestGenerated extends AbstractFirUastTypesTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInType() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/uast-kotlin-fir/testData/type"), Pattern.compile("^(.+)\\.kt$"), null, true);
}
@TestMetadata("unresolved.kt")
public void testUnresolved() throws Exception {
runTest("plugins/uast-kotlin-fir/testData/type/unresolved.kt");
}
}