diff --git a/plugins/uast-kotlin-base/src/org/jetbrains/uast/kotlin/expressions/KotlinUBinaryExpressionWithType.kt b/plugins/uast-kotlin-base/src/org/jetbrains/uast/kotlin/expressions/KotlinUBinaryExpressionWithType.kt new file mode 100644 index 00000000000..4301848c1f0 --- /dev/null +++ b/plugins/uast-kotlin-base/src/org/jetbrains/uast/kotlin/expressions/KotlinUBinaryExpressionWithType.kt @@ -0,0 +1,37 @@ +/* + * 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.kotlin + +import org.jetbrains.kotlin.lexer.KtTokens +import org.jetbrains.kotlin.psi.KtBinaryExpressionWithTypeRHS +import org.jetbrains.uast.* + +class KotlinUBinaryExpressionWithType( + override val sourcePsi: KtBinaryExpressionWithTypeRHS, + givenParent: UElement? +) : KotlinAbstractUExpression(givenParent), UBinaryExpressionWithType, KotlinUElementWithType, KotlinEvaluatableUElement { + override val operand by lz { + baseResolveProviderService.baseKotlinConverter.convertOrEmpty(sourcePsi.left, this) + } + + override val type by lz { + sourcePsi.right?.let { + baseResolveProviderService.resolveToType(it, this) + } ?: UastErrorType + } + + override val typeReference by lz { + sourcePsi.right?.let { + KotlinUTypeReferenceExpression(it, this) { type } + } + } + + override val operationKind = when (sourcePsi.operationReference.getReferencedNameElementType()) { + KtTokens.AS_KEYWORD -> UastBinaryExpressionWithTypeKind.TYPE_CAST + KtTokens.AS_SAFE -> KotlinBinaryExpressionWithTypeKinds.SAFE_TYPE_CAST + else -> UastBinaryExpressionWithTypeKind.UNKNOWN + } +} diff --git a/plugins/uast-kotlin-fir/src/org/jetbrains/uast/kotlin/FirKotlinConverter.kt b/plugins/uast-kotlin-fir/src/org/jetbrains/uast/kotlin/FirKotlinConverter.kt index 051597de56b..5b719df962d 100644 --- a/plugins/uast-kotlin-fir/src/org/jetbrains/uast/kotlin/FirKotlinConverter.kt +++ b/plugins/uast-kotlin-fir/src/org/jetbrains/uast/kotlin/FirKotlinConverter.kt @@ -291,6 +291,7 @@ internal object FirKotlinConverter : BaseKotlinConverter { is KtIfExpression -> expr(build(::KotlinUIfExpression)) + is KtBinaryExpressionWithTypeRHS -> expr(build(::KotlinUBinaryExpressionWithType)) is KtIsExpression -> expr(build(::KotlinUTypeCheckExpression)) else -> expr(build(::UnknownKotlinExpression)) diff --git a/plugins/uast-kotlin-fir/testData/legacyRenderLog/CycleInTypeParameters.log.fir.txt b/plugins/uast-kotlin-fir/testData/legacyRenderLog/CycleInTypeParameters.log.fir.txt index 576e2abadb5..66a3f98d7dc 100644 --- a/plugins/uast-kotlin-fir/testData/legacyRenderLog/CycleInTypeParameters.log.fir.txt +++ b/plugins/uast-kotlin-fir/testData/legacyRenderLog/CycleInTypeParameters.log.fir.txt @@ -1,7 +1,9 @@ UFile (package = ) UClass (name = CycleInTypeParametersKt) UField (name = a) - [!] UnknownKotlinExpression (BINARY_WITH_TYPE) + UBinaryExpressionWithType + ULiteralExpression (value = "not-yet-compile-time-constant") + UTypeReferenceExpression (name = Device) UMethod (name = getA) UClass (name = Device) UMethod (name = Device) diff --git a/plugins/uast-kotlin-fir/testData/legacyRenderLog/CycleInTypeParameters.render.fir.txt b/plugins/uast-kotlin-fir/testData/legacyRenderLog/CycleInTypeParameters.render.fir.txt index a605d47b724..6e1c64dfe02 100644 --- a/plugins/uast-kotlin-fir/testData/legacyRenderLog/CycleInTypeParameters.render.fir.txt +++ b/plugins/uast-kotlin-fir/testData/legacyRenderLog/CycleInTypeParameters.render.fir.txt @@ -1,5 +1,5 @@ public final class CycleInTypeParametersKt { - private static final var a: Device = [!] UnknownKotlinExpression (BINARY_WITH_TYPE) + private static final var a: Device = "not-yet-compile-time-constant" as? Device public static final fun getA() : Device = UastEmptyExpression } diff --git a/plugins/uast-kotlin-fir/testData/legacyTypes/CycleInTypeParameters.types.fir.txt b/plugins/uast-kotlin-fir/testData/legacyTypes/CycleInTypeParameters.types.fir.txt index 142b893c998..e55dbd2c121 100644 --- a/plugins/uast-kotlin-fir/testData/legacyTypes/CycleInTypeParameters.types.fir.txt +++ b/plugins/uast-kotlin-fir/testData/legacyTypes/CycleInTypeParameters.types.fir.txt @@ -1,7 +1,9 @@ UFile (package = ) [public final class CycleInTypeParametersKt {...] UClass (name = CycleInTypeParametersKt) [public final class CycleInTypeParametersKt {...}] - UField (name = a) [private static final var a: Device = [!] UnknownKotlinExpression (BINARY_WITH_TYPE)] - [!] UnknownKotlinExpression (BINARY_WITH_TYPE) [[!] UnknownKotlinExpression (BINARY_WITH_TYPE)] + UField (name = a) [private static final var a: Device = "not-yet-compile-time-constant" as? Device] + UBinaryExpressionWithType ["not-yet-compile-time-constant" as? Device] : PsiType:Device + ULiteralExpression (value = "not-yet-compile-time-constant") ["not-yet-compile-time-constant"] : PsiType:Void + UTypeReferenceExpression (name = Device) [Device] UMethod (name = getA) [public static final fun getA() : Device = UastEmptyExpression] UClass (name = Device) [public final class Device {...}] UMethod (name = Device) [public fun Device() = UastEmptyExpression] diff --git a/plugins/uast-kotlin-fir/testData/legacyValues/CycleInTypeParameters.values.fir.txt b/plugins/uast-kotlin-fir/testData/legacyValues/CycleInTypeParameters.values.fir.txt index e453579ded9..aa4c9858edf 100644 --- a/plugins/uast-kotlin-fir/testData/legacyValues/CycleInTypeParameters.values.fir.txt +++ b/plugins/uast-kotlin-fir/testData/legacyValues/CycleInTypeParameters.values.fir.txt @@ -1,7 +1,9 @@ UFile (package = ) [public final class CycleInTypeParametersKt {...] UClass (name = CycleInTypeParametersKt) [public final class CycleInTypeParametersKt {...}] - UField (name = a) [private static final var a: Device = [!] UnknownKotlinExpression (BINARY_WITH_TYPE)] - [!] UnknownKotlinExpression (BINARY_WITH_TYPE) [[!] UnknownKotlinExpression (BINARY_WITH_TYPE)] = Undetermined + UField (name = a) [private static final var a: Device = "not-yet-compile-time-constant" as? Device] + UBinaryExpressionWithType ["not-yet-compile-time-constant" as? Device] = Undetermined + ULiteralExpression (value = "not-yet-compile-time-constant") ["not-yet-compile-time-constant"] = "not-yet-compile-time-constant" + UTypeReferenceExpression (name = Device) [Device] = Undetermined UMethod (name = getA) [public static final fun getA() : Device = UastEmptyExpression] UClass (name = Device) [public final class Device {...}] UMethod (name = Device) [public fun Device() = UastEmptyExpression] diff --git a/plugins/uast-kotlin-fir/testData/type/typeCast.kt b/plugins/uast-kotlin-fir/testData/type/typeCast.kt new file mode 100644 index 00000000000..c089680d1d3 --- /dev/null +++ b/plugins/uast-kotlin-fir/testData/type/typeCast.kt @@ -0,0 +1,25 @@ +import java.lang.Runnable + +fun stringConsumer(s: String) { +} + +fun foo(x: Any, isSafe: Boolean) = + if (isSafe) x as Runnable else x as? Runnable + +fun box(): String { + // Unit as Any + val x = stringConsumer("Hi") as Any + if (x != Unit) return "Fail: $x" + + // Unit as? Any + val y = stringConsumer("Hi, again") as Any + if (y != Unit) return "Fail: $y" + + val r = object : Runnable { + override fun run() {} + } + if (foo(r, true) !=== r) return "Fail: $r" + if (foo(r, false) !=== r) return "Fail: $r" + + return "OK" +} diff --git a/plugins/uast-kotlin-fir/testData/type/typeCast.types.fe10.txt b/plugins/uast-kotlin-fir/testData/type/typeCast.types.fe10.txt new file mode 100644 index 00000000000..b7cc052d393 --- /dev/null +++ b/plugins/uast-kotlin-fir/testData/type/typeCast.types.fe10.txt @@ -0,0 +1,93 @@ +UFile (package = ) [import java.lang.Runnable...] + UImportStatement (isOnDemand = false) [import java.lang.Runnable] + UClass (name = TypeCastKt) [public final class TypeCastKt {...}] + UMethod (name = stringConsumer) [public static final fun stringConsumer(@org.jetbrains.annotations.NotNull s: java.lang.String) : void {...}] + UParameter (name = s) [@org.jetbrains.annotations.NotNull var s: java.lang.String] + UAnnotation (fqName = org.jetbrains.annotations.NotNull) [@org.jetbrains.annotations.NotNull] + UBlockExpression [{...}] : PsiType:void + UMethod (name = foo) [public static final fun foo(@org.jetbrains.annotations.NotNull x: java.lang.Object, @org.jetbrains.annotations.NotNull isSafe: boolean) : java.lang.Runnable {...}] + UParameter (name = x) [@org.jetbrains.annotations.NotNull var x: java.lang.Object] + UAnnotation (fqName = org.jetbrains.annotations.NotNull) [@org.jetbrains.annotations.NotNull] + UParameter (name = isSafe) [@org.jetbrains.annotations.NotNull var isSafe: boolean] + UAnnotation (fqName = org.jetbrains.annotations.NotNull) [@org.jetbrains.annotations.NotNull] + UBlockExpression [{...}] + UReturnExpression [return if (isSafe) x as java.lang.Runnable else x as? java.lang.Runnable] + UIfExpression [if (isSafe) x as java.lang.Runnable else x as? java.lang.Runnable] : PsiType:Runnable + USimpleNameReferenceExpression (identifier = isSafe) [isSafe] : PsiType:boolean + UBinaryExpressionWithType [x as java.lang.Runnable] : PsiType:Runnable + USimpleNameReferenceExpression (identifier = x) [x] : PsiType:Object + UTypeReferenceExpression (name = java.lang.Runnable) [java.lang.Runnable] + UBinaryExpressionWithType [x as? java.lang.Runnable] : PsiType:Runnable + USimpleNameReferenceExpression (identifier = x) [x] : PsiType:Object + UTypeReferenceExpression (name = java.lang.Runnable) [java.lang.Runnable] + UMethod (name = box) [public static final fun box() : java.lang.String {...}] + UBlockExpression [{...}] : PsiType:Void + UDeclarationsExpression [var x: java.lang.Object = stringConsumer("Hi") as java.lang.Object] + ULocalVariable (name = x) [var x: java.lang.Object = stringConsumer("Hi") as java.lang.Object] + UBinaryExpressionWithType [stringConsumer("Hi") as java.lang.Object] : PsiType:Object + UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1)) [stringConsumer("Hi")] : PsiType:void + UIdentifier (Identifier (stringConsumer)) [UIdentifier (Identifier (stringConsumer))] + USimpleNameReferenceExpression (identifier = stringConsumer, resolvesTo = null) [stringConsumer] : PsiType:void + ULiteralExpression (value = "Hi") ["Hi"] : PsiType:String + UTypeReferenceExpression (name = java.lang.Object) [java.lang.Object] + UIfExpression [if (x != Unit) return "Fail: " + x] : PsiType:void + UBinaryExpression (operator = !=) [x != Unit] : PsiType:boolean + USimpleNameReferenceExpression (identifier = x) [x] : PsiType:Object + USimpleNameReferenceExpression (identifier = Unit) [Unit] : PsiType:void + UReturnExpression [return "Fail: " + x] : PsiType:Void + UPolyadicExpression (operator = +) ["Fail: " + x] : PsiType:String + ULiteralExpression (value = "Fail: ") ["Fail: "] : PsiType:String + USimpleNameReferenceExpression (identifier = x) [x] : PsiType:Object + UDeclarationsExpression [var y: java.lang.Object = stringConsumer("Hi, again") as java.lang.Object] + ULocalVariable (name = y) [var y: java.lang.Object = stringConsumer("Hi, again") as java.lang.Object] + UBinaryExpressionWithType [stringConsumer("Hi, again") as java.lang.Object] : PsiType:Object + UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1)) [stringConsumer("Hi, again")] : PsiType:void + UIdentifier (Identifier (stringConsumer)) [UIdentifier (Identifier (stringConsumer))] + USimpleNameReferenceExpression (identifier = stringConsumer, resolvesTo = null) [stringConsumer] : PsiType:void + ULiteralExpression (value = "Hi, again") ["Hi, again"] : PsiType:String + UTypeReferenceExpression (name = java.lang.Object) [java.lang.Object] + UIfExpression [if (y != Unit) return "Fail: " + y] : PsiType:void + UBinaryExpression (operator = !=) [y != Unit] : PsiType:boolean + USimpleNameReferenceExpression (identifier = y) [y] : PsiType:Object + USimpleNameReferenceExpression (identifier = Unit) [Unit] : PsiType:void + UReturnExpression [return "Fail: " + y] : PsiType:Void + UPolyadicExpression (operator = +) ["Fail: " + y] : PsiType:String + ULiteralExpression (value = "Fail: ") ["Fail: "] : PsiType:String + USimpleNameReferenceExpression (identifier = y) [y] : PsiType:Object + UDeclarationsExpression [var r: = anonymous object : Runnable {... }] + ULocalVariable (name = r) [var r: = anonymous object : Runnable {... }] + UObjectLiteralExpression [anonymous object : Runnable {... }] : PsiType:Runnable + UClass (name = null) [final class null : java.lang.Runnable {...}] + UMethod (name = run) [public fun run() : void {...}] + UBlockExpression [{...}] : PsiType:void + UMethod (name = ) [private fun () = UastEmptyExpression] + UIfExpression [if (foo(r, true) !== UastEmptyExpression UastEmptyExpression) return "Fail: " + r] : PsiType:void + UBinaryExpression (operator = !==) [foo(r, true) !== UastEmptyExpression UastEmptyExpression] : PsiType:boolean + UCallExpression (kind = UastCallKind(name='method_call'), argCount = 2)) [foo(r, true)] : PsiType:Runnable + UIdentifier (Identifier (foo)) [UIdentifier (Identifier (foo))] + USimpleNameReferenceExpression (identifier = foo, resolvesTo = null) [foo] : PsiType:Runnable + USimpleNameReferenceExpression (identifier = r) [r] : PsiType: + ULiteralExpression (value = true) [true] : PsiType:boolean + UBinaryExpression (operator = ) [UastEmptyExpression UastEmptyExpression] + UastEmptyExpression [UastEmptyExpression] + UastEmptyExpression [UastEmptyExpression] + UReturnExpression [return "Fail: " + r] : PsiType:Void + UPolyadicExpression (operator = +) ["Fail: " + r] : PsiType:String + ULiteralExpression (value = "Fail: ") ["Fail: "] : PsiType:String + USimpleNameReferenceExpression (identifier = r) [r] : PsiType: + UIfExpression [if (foo(r, false) !== UastEmptyExpression UastEmptyExpression) return "Fail: " + r] : PsiType:void + UBinaryExpression (operator = !==) [foo(r, false) !== UastEmptyExpression UastEmptyExpression] : PsiType:boolean + UCallExpression (kind = UastCallKind(name='method_call'), argCount = 2)) [foo(r, false)] : PsiType:Runnable + UIdentifier (Identifier (foo)) [UIdentifier (Identifier (foo))] + USimpleNameReferenceExpression (identifier = foo, resolvesTo = null) [foo] : PsiType:Runnable + USimpleNameReferenceExpression (identifier = r) [r] : PsiType: + ULiteralExpression (value = false) [false] : PsiType:boolean + UBinaryExpression (operator = ) [UastEmptyExpression UastEmptyExpression] + UastEmptyExpression [UastEmptyExpression] + UastEmptyExpression [UastEmptyExpression] + UReturnExpression [return "Fail: " + r] : PsiType:Void + UPolyadicExpression (operator = +) ["Fail: " + r] : PsiType:String + ULiteralExpression (value = "Fail: ") ["Fail: "] : PsiType:String + USimpleNameReferenceExpression (identifier = r) [r] : PsiType: + UReturnExpression [return "OK"] : PsiType:Void + ULiteralExpression (value = "OK") ["OK"] : PsiType:String diff --git a/plugins/uast-kotlin-fir/testData/type/typeCast.types.fir.txt b/plugins/uast-kotlin-fir/testData/type/typeCast.types.fir.txt new file mode 100644 index 00000000000..fd39e3a617f --- /dev/null +++ b/plugins/uast-kotlin-fir/testData/type/typeCast.types.fir.txt @@ -0,0 +1,50 @@ +UFile (package = ) [import java.lang.Runnable...] + UImportStatement (isOnDemand = false) [import java.lang.Runnable] + UClass (name = TypeCastKt) [public final class TypeCastKt {...}] + UMethod (name = stringConsumer) [public static final fun stringConsumer(s: java.lang.String) : void {...}] + UParameter (name = s) [var s: java.lang.String] + UBlockExpression [{...}] : PsiType:Unit + UMethod (name = foo) [public static final fun foo(x: java.lang.Object, isSafe: boolean) : java.lang.Runnable {...}] + UParameter (name = x) [var x: java.lang.Object] + UParameter (name = isSafe) [var isSafe: boolean] + UBlockExpression [{...}] + UReturnExpression [return if ([!] UnknownKotlinExpression (REFERENCE_EXPRESSION)) [!] UnknownKotlinExpression (REFERENCE_EXPRESSION) as java.lang.Runnable else [!] UnknownKotlinExpression (REFERENCE_EXPRESSION) as? java.lang.Runnable] + UIfExpression [if ([!] UnknownKotlinExpression (REFERENCE_EXPRESSION)) [!] UnknownKotlinExpression (REFERENCE_EXPRESSION) as java.lang.Runnable else [!] UnknownKotlinExpression (REFERENCE_EXPRESSION) as? java.lang.Runnable] : PsiType:Runnable + [!] UnknownKotlinExpression (REFERENCE_EXPRESSION) [[!] UnknownKotlinExpression (REFERENCE_EXPRESSION)] + UBinaryExpressionWithType [[!] UnknownKotlinExpression (REFERENCE_EXPRESSION) as java.lang.Runnable] : PsiType:Runnable + [!] UnknownKotlinExpression (REFERENCE_EXPRESSION) [[!] UnknownKotlinExpression (REFERENCE_EXPRESSION)] + UTypeReferenceExpression (name = java.lang.Runnable) [java.lang.Runnable] + UBinaryExpressionWithType [[!] UnknownKotlinExpression (REFERENCE_EXPRESSION) as? java.lang.Runnable] : PsiType:Runnable + [!] UnknownKotlinExpression (REFERENCE_EXPRESSION) [[!] UnknownKotlinExpression (REFERENCE_EXPRESSION)] + UTypeReferenceExpression (name = java.lang.Runnable) [java.lang.Runnable] + UMethod (name = box) [public static final fun box() : java.lang.String {...}] + UBlockExpression [{...}] : PsiType:Void + [!] UnknownKotlinExpression (PROPERTY) [[!] UnknownKotlinExpression (PROPERTY)] + UIfExpression [if ([!] UnknownKotlinExpression (BINARY_EXPRESSION)) return "Fail: " + [!] UnknownKotlinExpression (REFERENCE_EXPRESSION)] : PsiType:Unit + [!] UnknownKotlinExpression (BINARY_EXPRESSION) [[!] UnknownKotlinExpression (BINARY_EXPRESSION)] + UReturnExpression [return "Fail: " + [!] UnknownKotlinExpression (REFERENCE_EXPRESSION)] : PsiType:Void + UPolyadicExpression (operator = +) ["Fail: " + [!] UnknownKotlinExpression (REFERENCE_EXPRESSION)] : PsiType:String + ULiteralExpression (value = "Fail: ") ["Fail: "] : PsiType:String + [!] UnknownKotlinExpression (REFERENCE_EXPRESSION) [[!] UnknownKotlinExpression (REFERENCE_EXPRESSION)] + [!] UnknownKotlinExpression (PROPERTY) [[!] UnknownKotlinExpression (PROPERTY)] + UIfExpression [if ([!] UnknownKotlinExpression (BINARY_EXPRESSION)) return "Fail: " + [!] UnknownKotlinExpression (REFERENCE_EXPRESSION)] : PsiType:Unit + [!] UnknownKotlinExpression (BINARY_EXPRESSION) [[!] UnknownKotlinExpression (BINARY_EXPRESSION)] + UReturnExpression [return "Fail: " + [!] UnknownKotlinExpression (REFERENCE_EXPRESSION)] : PsiType:Void + UPolyadicExpression (operator = +) ["Fail: " + [!] UnknownKotlinExpression (REFERENCE_EXPRESSION)] : PsiType:String + ULiteralExpression (value = "Fail: ") ["Fail: "] : PsiType:String + [!] UnknownKotlinExpression (REFERENCE_EXPRESSION) [[!] UnknownKotlinExpression (REFERENCE_EXPRESSION)] + [!] UnknownKotlinExpression (PROPERTY) [[!] UnknownKotlinExpression (PROPERTY)] + UIfExpression [if ([!] UnknownKotlinExpression (BINARY_EXPRESSION)) return "Fail: " + [!] UnknownKotlinExpression (REFERENCE_EXPRESSION)] : PsiType:Unit + [!] UnknownKotlinExpression (BINARY_EXPRESSION) [[!] UnknownKotlinExpression (BINARY_EXPRESSION)] + UReturnExpression [return "Fail: " + [!] UnknownKotlinExpression (REFERENCE_EXPRESSION)] : PsiType:Void + UPolyadicExpression (operator = +) ["Fail: " + [!] UnknownKotlinExpression (REFERENCE_EXPRESSION)] : PsiType:String + ULiteralExpression (value = "Fail: ") ["Fail: "] : PsiType:String + [!] UnknownKotlinExpression (REFERENCE_EXPRESSION) [[!] UnknownKotlinExpression (REFERENCE_EXPRESSION)] + UIfExpression [if ([!] UnknownKotlinExpression (BINARY_EXPRESSION)) return "Fail: " + [!] UnknownKotlinExpression (REFERENCE_EXPRESSION)] : PsiType:Unit + [!] UnknownKotlinExpression (BINARY_EXPRESSION) [[!] UnknownKotlinExpression (BINARY_EXPRESSION)] + UReturnExpression [return "Fail: " + [!] UnknownKotlinExpression (REFERENCE_EXPRESSION)] : PsiType:Void + UPolyadicExpression (operator = +) ["Fail: " + [!] UnknownKotlinExpression (REFERENCE_EXPRESSION)] : PsiType:String + ULiteralExpression (value = "Fail: ") ["Fail: "] : PsiType:String + [!] UnknownKotlinExpression (REFERENCE_EXPRESSION) [[!] UnknownKotlinExpression (REFERENCE_EXPRESSION)] + UReturnExpression [return "OK"] : PsiType:Void + ULiteralExpression (value = "OK") ["OK"] : PsiType:String diff --git a/plugins/uast-kotlin-fir/testData/type/withGeneric.kt b/plugins/uast-kotlin-fir/testData/type/withGeneric.kt new file mode 100644 index 00000000000..4346853c47e --- /dev/null +++ b/plugins/uast-kotlin-fir/testData/type/withGeneric.kt @@ -0,0 +1,32 @@ +fun test1() = null as T + +fun test2(): T { + val a : Any? = null + return a as T +} + +fun test3() = null as T + +fun castToString(t: T) { + t as String +} + +fun box(): String { + if (test1() != null) return "fail: test1" + if (test2() != null) return "fail: test2" + var result3 = "fail" + try { + test3() + } + catch(e: NullPointerException) { + result3 = "OK" + } + if (result3 != "OK") return "fail: test3" + + try { + castToString(null) + } catch (e: Exception) { + return "OK" + } + return "Fail" +} diff --git a/plugins/uast-kotlin-fir/testData/type/withGeneric.types.fe10.txt b/plugins/uast-kotlin-fir/testData/type/withGeneric.types.fe10.txt new file mode 100644 index 00000000000..4532e9ae417 --- /dev/null +++ b/plugins/uast-kotlin-fir/testData/type/withGeneric.types.fe10.txt @@ -0,0 +1,83 @@ +UFile (package = ) [public final class WithGenericKt {...] + UClass (name = WithGenericKt) [public final class WithGenericKt {...}] + UMethod (name = test1) [public static final fun test1() : T {...}] + UBlockExpression [{...}] + UReturnExpression [return null as T] + UBinaryExpressionWithType [null as T] : PsiType:T + ULiteralExpression (value = null) [null] : PsiType:Void + UTypeReferenceExpression (name = T) [T] + UMethod (name = test2) [public static final fun test2() : T {...}] + UBlockExpression [{...}] : PsiType:Void + UDeclarationsExpression [var a: java.lang.Object = null] + ULocalVariable (name = a) [var a: java.lang.Object = null] + ULiteralExpression (value = null) [null] : PsiType:Void + UReturnExpression [return a as T] : PsiType:Void + UBinaryExpressionWithType [a as T] : PsiType:T + USimpleNameReferenceExpression (identifier = a) [a] : PsiType:Object + UTypeReferenceExpression (name = T) [T] + UMethod (name = test3) [public static final fun test3() : T {...}] + UBlockExpression [{...}] + UReturnExpression [return null as T] + UBinaryExpressionWithType [null as T] : PsiType:T + ULiteralExpression (value = null) [null] : PsiType:Void + UTypeReferenceExpression (name = T) [T] + UMethod (name = castToString) [public static final fun castToString(@org.jetbrains.annotations.Nullable t: T) : void {...}] + UParameter (name = t) [@org.jetbrains.annotations.Nullable var t: T] + UAnnotation (fqName = org.jetbrains.annotations.Nullable) [@org.jetbrains.annotations.Nullable] + UBlockExpression [{...}] : PsiType:String + UBinaryExpressionWithType [t as java.lang.String] : PsiType:String + USimpleNameReferenceExpression (identifier = t) [t] : PsiType:T + UTypeReferenceExpression (name = java.lang.String) [java.lang.String] + UMethod (name = box) [public static final fun box() : java.lang.String {...}] + UBlockExpression [{...}] : PsiType:Void + UIfExpression [if (test1() != null) return "fail: test1"] : PsiType:void + UBinaryExpression (operator = !=) [test1() != null] : PsiType:boolean + UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0)) [test1()] : PsiType:int + UIdentifier (Identifier (test1)) [UIdentifier (Identifier (test1))] + USimpleNameReferenceExpression (identifier = test1, resolvesTo = null) [test1] : PsiType:int + ULiteralExpression (value = null) [null] : PsiType:Void + UReturnExpression [return "fail: test1"] : PsiType:Void + ULiteralExpression (value = "fail: test1") ["fail: test1"] : PsiType:String + UIfExpression [if (test2() != null) return "fail: test2"] : PsiType:void + UBinaryExpression (operator = !=) [test2() != null] : PsiType:boolean + UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0)) [test2()] : PsiType:int + UIdentifier (Identifier (test2)) [UIdentifier (Identifier (test2))] + USimpleNameReferenceExpression (identifier = test2, resolvesTo = null) [test2] : PsiType:int + ULiteralExpression (value = null) [null] : PsiType:Void + UReturnExpression [return "fail: test2"] : PsiType:Void + ULiteralExpression (value = "fail: test2") ["fail: test2"] : PsiType:String + UDeclarationsExpression [var result3: java.lang.String = "fail"] + ULocalVariable (name = result3) [var result3: java.lang.String = "fail"] + ULiteralExpression (value = "fail") ["fail"] : PsiType:String + UTryExpression [try {...] : PsiType:Object + UBlockExpression [{...}] : PsiType:int + UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0)) [test3()] : PsiType:int + UIdentifier (Identifier (test3)) [UIdentifier (Identifier (test3))] + USimpleNameReferenceExpression (identifier = test3, resolvesTo = null) [test3] : PsiType:int + UCatchClause (e) [catch (@org.jetbrains.annotations.NotNull var e: java.lang.NullPointerException) {...}] + UParameter (name = e) [@org.jetbrains.annotations.NotNull var e: java.lang.NullPointerException] + UAnnotation (fqName = org.jetbrains.annotations.NotNull) [@org.jetbrains.annotations.NotNull] + UBlockExpression [{...}] : PsiType:void + UBinaryExpression (operator = =) [result3 = "OK"] : PsiType:void + USimpleNameReferenceExpression (identifier = result3) [result3] : PsiType:String + ULiteralExpression (value = "OK") ["OK"] : PsiType:String + UIfExpression [if (result3 != "OK") return "fail: test3"] : PsiType:void + UBinaryExpression (operator = !=) [result3 != "OK"] : PsiType:boolean + USimpleNameReferenceExpression (identifier = result3) [result3] : PsiType:String + ULiteralExpression (value = "OK") ["OK"] : PsiType:String + UReturnExpression [return "fail: test3"] : PsiType:Void + ULiteralExpression (value = "fail: test3") ["fail: test3"] : PsiType:String + UTryExpression [try {...] : PsiType:void + UBlockExpression [{...}] : PsiType:void + UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1)) [castToString(null)] : PsiType:void + UIdentifier (Identifier (castToString)) [UIdentifier (Identifier (castToString))] + USimpleNameReferenceExpression (identifier = castToString, resolvesTo = null) [castToString] : PsiType:void + ULiteralExpression (value = null) [null] : PsiType:Void + UCatchClause (e) [catch (@org.jetbrains.annotations.NotNull var e: java.lang.Exception) {...}] + UParameter (name = e) [@org.jetbrains.annotations.NotNull var e: java.lang.Exception] + UAnnotation (fqName = org.jetbrains.annotations.NotNull) [@org.jetbrains.annotations.NotNull] + UBlockExpression [{...}] : PsiType:Void + UReturnExpression [return "OK"] : PsiType:Void + ULiteralExpression (value = "OK") ["OK"] : PsiType:String + UReturnExpression [return "Fail"] : PsiType:Void + ULiteralExpression (value = "Fail") ["Fail"] : PsiType:String diff --git a/plugins/uast-kotlin-fir/testData/type/withGeneric.types.fir.txt b/plugins/uast-kotlin-fir/testData/type/withGeneric.types.fir.txt new file mode 100644 index 00000000000..47c9013bdc3 --- /dev/null +++ b/plugins/uast-kotlin-fir/testData/type/withGeneric.types.fir.txt @@ -0,0 +1,46 @@ +UFile (package = ) [public final class WithGenericKt {...] + UClass (name = WithGenericKt) [public final class WithGenericKt {...}] + UMethod (name = test1) [public static final fun test1() : T {...}] + UBlockExpression [{...}] + UReturnExpression [return "not-yet-compile-time-constant" as T] + UBinaryExpressionWithType ["not-yet-compile-time-constant" as T] : PsiType:T + ULiteralExpression (value = "not-yet-compile-time-constant") ["not-yet-compile-time-constant"] : PsiType:Void + UTypeReferenceExpression (name = T) [T] + UMethod (name = test2) [public static final fun test2() : T {...}] + UBlockExpression [{...}] : PsiType:Void + [!] UnknownKotlinExpression (PROPERTY) [[!] UnknownKotlinExpression (PROPERTY)] + UReturnExpression [return [!] UnknownKotlinExpression (REFERENCE_EXPRESSION) as T] : PsiType:Void + UBinaryExpressionWithType [[!] UnknownKotlinExpression (REFERENCE_EXPRESSION) as T] : PsiType:T + [!] UnknownKotlinExpression (REFERENCE_EXPRESSION) [[!] UnknownKotlinExpression (REFERENCE_EXPRESSION)] + UTypeReferenceExpression (name = T) [T] + UMethod (name = test3) [public static final fun test3() : T {...}] + UBlockExpression [{...}] + UReturnExpression [return "not-yet-compile-time-constant" as T] + UBinaryExpressionWithType ["not-yet-compile-time-constant" as T] : PsiType:T + ULiteralExpression (value = "not-yet-compile-time-constant") ["not-yet-compile-time-constant"] : PsiType:Void + UTypeReferenceExpression (name = T) [T] + UMethod (name = castToString) [public static final fun castToString(t: T) : void {...}] + UParameter (name = t) [var t: T] + UBlockExpression [{...}] : PsiType:String + UBinaryExpressionWithType [[!] UnknownKotlinExpression (REFERENCE_EXPRESSION) as java.lang.String] : PsiType:String + [!] UnknownKotlinExpression (REFERENCE_EXPRESSION) [[!] UnknownKotlinExpression (REFERENCE_EXPRESSION)] + UTypeReferenceExpression (name = java.lang.String) [java.lang.String] + UMethod (name = box) [public static final fun box() : java.lang.String {...}] + UBlockExpression [{...}] : PsiType:Void + UIfExpression [if ([!] UnknownKotlinExpression (BINARY_EXPRESSION)) return "fail: test1"] : PsiType:Unit + [!] UnknownKotlinExpression (BINARY_EXPRESSION) [[!] UnknownKotlinExpression (BINARY_EXPRESSION)] + UReturnExpression [return "fail: test1"] : PsiType:Void + ULiteralExpression (value = "fail: test1") ["fail: test1"] : PsiType:String + UIfExpression [if ([!] UnknownKotlinExpression (BINARY_EXPRESSION)) return "fail: test2"] : PsiType:Unit + [!] UnknownKotlinExpression (BINARY_EXPRESSION) [[!] UnknownKotlinExpression (BINARY_EXPRESSION)] + UReturnExpression [return "fail: test2"] : PsiType:Void + ULiteralExpression (value = "fail: test2") ["fail: test2"] : PsiType:String + [!] UnknownKotlinExpression (PROPERTY) [[!] UnknownKotlinExpression (PROPERTY)] + [!] UnknownKotlinExpression (TRY) [[!] UnknownKotlinExpression (TRY)] + UIfExpression [if ([!] UnknownKotlinExpression (BINARY_EXPRESSION)) return "fail: test3"] : PsiType:Unit + [!] UnknownKotlinExpression (BINARY_EXPRESSION) [[!] UnknownKotlinExpression (BINARY_EXPRESSION)] + UReturnExpression [return "fail: test3"] : PsiType:Void + ULiteralExpression (value = "fail: test3") ["fail: test3"] : PsiType:String + [!] UnknownKotlinExpression (TRY) [[!] UnknownKotlinExpression (TRY)] + UReturnExpression [return "Fail"] : PsiType:Void + ULiteralExpression (value = "Fail") ["Fail"] : PsiType:String diff --git a/plugins/uast-kotlin-fir/tests/org/jetbrains/uast/test/kotlin/FE1UastTypesTestGenerated.java b/plugins/uast-kotlin-fir/tests/org/jetbrains/uast/test/kotlin/FE1UastTypesTestGenerated.java index 44cf8b692e9..3162e869b5b 100644 --- a/plugins/uast-kotlin-fir/tests/org/jetbrains/uast/test/kotlin/FE1UastTypesTestGenerated.java +++ b/plugins/uast-kotlin-fir/tests/org/jetbrains/uast/test/kotlin/FE1UastTypesTestGenerated.java @@ -29,6 +29,11 @@ public class FE1UastTypesTestGenerated extends AbstractFE1UastTypesTest { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/uast-kotlin-fir/testData/type"), Pattern.compile("^(.+)\\.kt$"), null, true); } + @TestMetadata("typeCast.kt") + public void testTypeCast() throws Exception { + runTest("plugins/uast-kotlin-fir/testData/type/typeCast.kt"); + } + @TestMetadata("typeCheck.kt") public void testTypeCheck() throws Exception { runTest("plugins/uast-kotlin-fir/testData/type/typeCheck.kt"); @@ -38,4 +43,9 @@ public class FE1UastTypesTestGenerated extends AbstractFE1UastTypesTest { public void testUnresolved() throws Exception { runTest("plugins/uast-kotlin-fir/testData/type/unresolved.kt"); } + + @TestMetadata("withGeneric.kt") + public void testWithGeneric() throws Exception { + runTest("plugins/uast-kotlin-fir/testData/type/withGeneric.kt"); + } } diff --git a/plugins/uast-kotlin-fir/tests/org/jetbrains/uast/test/kotlin/FirUastTypesTestGenerated.java b/plugins/uast-kotlin-fir/tests/org/jetbrains/uast/test/kotlin/FirUastTypesTestGenerated.java index d3327b50c0c..8f3a6ae2c58 100644 --- a/plugins/uast-kotlin-fir/tests/org/jetbrains/uast/test/kotlin/FirUastTypesTestGenerated.java +++ b/plugins/uast-kotlin-fir/tests/org/jetbrains/uast/test/kotlin/FirUastTypesTestGenerated.java @@ -29,6 +29,11 @@ public class FirUastTypesTestGenerated extends AbstractFirUastTypesTest { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/uast-kotlin-fir/testData/type"), Pattern.compile("^(.+)\\.kt$"), null, true); } + @TestMetadata("typeCast.kt") + public void testTypeCast() throws Exception { + runTest("plugins/uast-kotlin-fir/testData/type/typeCast.kt"); + } + @TestMetadata("typeCheck.kt") public void testTypeCheck() throws Exception { runTest("plugins/uast-kotlin-fir/testData/type/typeCheck.kt"); @@ -38,4 +43,9 @@ public class FirUastTypesTestGenerated extends AbstractFirUastTypesTest { public void testUnresolved() throws Exception { runTest("plugins/uast-kotlin-fir/testData/type/unresolved.kt"); } + + @TestMetadata("withGeneric.kt") + public void testWithGeneric() throws Exception { + runTest("plugins/uast-kotlin-fir/testData/type/withGeneric.kt"); + } } diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinCustomUBinaryExpressionWithType.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinCustomUBinaryExpressionWithType.kt new file mode 100644 index 00000000000..1f09287f77b --- /dev/null +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinCustomUBinaryExpressionWithType.kt @@ -0,0 +1,26 @@ +/* + * 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.kotlin + +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiType +import org.jetbrains.uast.* + +class KotlinCustomUBinaryExpressionWithType( + override val psi: PsiElement, + givenParent: UElement? +) : KotlinAbstractUExpression(givenParent), UBinaryExpressionWithType { + override lateinit var operand: UExpression + internal set + + override lateinit var operationKind: UastBinaryExpressionWithTypeKind + internal set + + override val type: PsiType by lz { typeReference?.type ?: UastErrorType } + + override var typeReference: UTypeReferenceExpression? = null + internal set +} diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUBinaryExpressionWithType.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUBinaryExpressionWithType.kt deleted file mode 100644 index 45986ee65fd..00000000000 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUBinaryExpressionWithType.kt +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2010-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.uast.kotlin - -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiType -import org.jetbrains.kotlin.lexer.KtTokens -import org.jetbrains.kotlin.psi.KtBinaryExpressionWithTypeRHS -import org.jetbrains.uast.* - -class KotlinUBinaryExpressionWithType( - override val sourcePsi: KtBinaryExpressionWithTypeRHS, - givenParent: UElement? -) : KotlinAbstractUExpression(givenParent), UBinaryExpressionWithType, - KotlinUElementWithType, KotlinEvaluatableUElement { - - override val operand by lz { KotlinConverter.convertOrEmpty(sourcePsi.left, this) } - override val type by lz { sourcePsi.right.toPsiType(this) } - - override val typeReference by lz { - sourcePsi.right?.let { KotlinUTypeReferenceExpression(it, this) } - } - - override val operationKind = when (sourcePsi.operationReference.getReferencedNameElementType()) { - KtTokens.AS_KEYWORD -> UastBinaryExpressionWithTypeKind.TYPE_CAST - KtTokens.AS_SAFE -> KotlinBinaryExpressionWithTypeKinds.SAFE_TYPE_CAST - else -> UastBinaryExpressionWithTypeKind.UNKNOWN - } -} - -class KotlinCustomUBinaryExpressionWithType( - override val psi: PsiElement, - givenParent: UElement? -) : KotlinAbstractUExpression(givenParent), UBinaryExpressionWithType { - lateinit override var operand: UExpression - internal set - - lateinit override var operationKind: UastBinaryExpressionWithTypeKind - internal set - - override val type: PsiType by lz { typeReference?.type ?: UastErrorType } - - override var typeReference: UTypeReferenceExpression? = null - internal set -}