diff --git a/plugins/uast-kotlin-base/src/org/jetbrains/uast/kotlin/expressions/KotlinUTypeCheckExpression.kt b/plugins/uast-kotlin-base/src/org/jetbrains/uast/kotlin/expressions/KotlinUTypeCheckExpression.kt new file mode 100644 index 00000000000..d4e86cb70eb --- /dev/null +++ b/plugins/uast-kotlin-base/src/org/jetbrains/uast/kotlin/expressions/KotlinUTypeCheckExpression.kt @@ -0,0 +1,39 @@ +/* + * 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.psi.KtIsExpression +import org.jetbrains.uast.UBinaryExpressionWithType +import org.jetbrains.uast.UElement +import org.jetbrains.uast.UastBinaryExpressionWithTypeKind +import org.jetbrains.uast.UastErrorType + +class KotlinUTypeCheckExpression( + override val sourcePsi: KtIsExpression, + givenParent: UElement? +) : KotlinAbstractUExpression(givenParent), UBinaryExpressionWithType, KotlinUElementWithType, KotlinEvaluatableUElement { + override val operand by lz { + baseResolveProviderService.baseKotlinConverter.convertOrEmpty(sourcePsi.leftHandSide, this) + } + + override val type by lz { + sourcePsi.typeReference?.let { + baseResolveProviderService.resolveToType(it, this) + } ?: UastErrorType + } + + override val typeReference by lz { + sourcePsi.typeReference?.let { + KotlinUTypeReferenceExpression(it, this) { type } + } + } + + override val operationKind = + if (sourcePsi.isNegated) + KotlinBinaryExpressionWithTypeKinds.NEGATED_INSTANCE_CHECK + else + UastBinaryExpressionWithTypeKind.INSTANCE_CHECK +} 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 9a43b948b94..051597de56b 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,8 @@ internal object FirKotlinConverter : BaseKotlinConverter { is KtIfExpression -> expr(build(::KotlinUIfExpression)) + is KtIsExpression -> expr(build(::KotlinUTypeCheckExpression)) + else -> expr(build(::UnknownKotlinExpression)) } } diff --git a/plugins/uast-kotlin-fir/testData/type/typeCheck.kt b/plugins/uast-kotlin-fir/testData/type/typeCheck.kt new file mode 100644 index 00000000000..98ca12d549b --- /dev/null +++ b/plugins/uast-kotlin-fir/testData/type/typeCheck.kt @@ -0,0 +1,6 @@ +fun Any?.asString(): String { + return if (x !is String) + x.toString() + else + x +} diff --git a/plugins/uast-kotlin-fir/testData/type/typeCheck.types.fe10.txt b/plugins/uast-kotlin-fir/testData/type/typeCheck.types.fe10.txt new file mode 100644 index 00000000000..e1d92027d65 --- /dev/null +++ b/plugins/uast-kotlin-fir/testData/type/typeCheck.types.fe10.txt @@ -0,0 +1,17 @@ +UFile (package = ) [public final class TypeCheckKt {...] + UClass (name = TypeCheckKt) [public final class TypeCheckKt {...}] + UMethod (name = asString) [public static final fun asString(@org.jetbrains.annotations.Nullable $this$asString: java.lang.Object) : java.lang.String {...}] + UParameter (name = $this$asString) [@org.jetbrains.annotations.Nullable var $this$asString: java.lang.Object] + UAnnotation (fqName = org.jetbrains.annotations.Nullable) [@org.jetbrains.annotations.Nullable] + UBlockExpression [{...}] : PsiType:Void + UReturnExpression [return if (x !is java.lang.String) x.() else x] : PsiType:Void + UIfExpression [if (x !is java.lang.String) x.() else x] : PsiType:String + UBinaryExpressionWithType [x !is java.lang.String] : PsiType:boolean + USimpleNameReferenceExpression (identifier = x) [x] + UTypeReferenceExpression (name = java.lang.String) [java.lang.String] + UQualifiedReferenceExpression [x.()] : PsiType: + USimpleNameReferenceExpression (identifier = x) [x] + UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0)) [()] : PsiType: + UIdentifier (Identifier (toString)) [UIdentifier (Identifier (toString))] + USimpleNameReferenceExpression (identifier = , resolvesTo = null) [] : PsiType: + USimpleNameReferenceExpression (identifier = x) [x] diff --git a/plugins/uast-kotlin-fir/testData/type/typeCheck.types.fir.txt b/plugins/uast-kotlin-fir/testData/type/typeCheck.types.fir.txt new file mode 100644 index 00000000000..12646e1945a --- /dev/null +++ b/plugins/uast-kotlin-fir/testData/type/typeCheck.types.fir.txt @@ -0,0 +1,12 @@ +UFile (package = ) [public final class TypeCheckKt {...] + UClass (name = TypeCheckKt) [public final class TypeCheckKt {...}] + UMethod (name = asString) [public static final fun asString($this$asString: java.lang.Object) : java.lang.String {...}] + UParameter (name = $this$asString) [var $this$asString: java.lang.Object] + UBlockExpression [{...}] : PsiType:Void + UReturnExpression [return if ([!] UnknownKotlinExpression (REFERENCE_EXPRESSION) !is java.lang.String) [!] UnknownKotlinExpression (DOT_QUALIFIED_EXPRESSION) else [!] UnknownKotlinExpression (REFERENCE_EXPRESSION)] : PsiType:Void + UIfExpression [if ([!] UnknownKotlinExpression (REFERENCE_EXPRESSION) !is java.lang.String) [!] UnknownKotlinExpression (DOT_QUALIFIED_EXPRESSION) else [!] UnknownKotlinExpression (REFERENCE_EXPRESSION)] : PsiType:String + UBinaryExpressionWithType [[!] UnknownKotlinExpression (REFERENCE_EXPRESSION) !is java.lang.String] : PsiType:boolean + [!] UnknownKotlinExpression (REFERENCE_EXPRESSION) [[!] UnknownKotlinExpression (REFERENCE_EXPRESSION)] + UTypeReferenceExpression (name = java.lang.String) [java.lang.String] + [!] UnknownKotlinExpression (DOT_QUALIFIED_EXPRESSION) [[!] UnknownKotlinExpression (DOT_QUALIFIED_EXPRESSION)] + [!] UnknownKotlinExpression (REFERENCE_EXPRESSION) [[!] UnknownKotlinExpression (REFERENCE_EXPRESSION)] 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 bd7a2d71a17..44cf8b692e9 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("typeCheck.kt") + public void testTypeCheck() throws Exception { + runTest("plugins/uast-kotlin-fir/testData/type/typeCheck.kt"); + } + @TestMetadata("unresolved.kt") public void testUnresolved() throws Exception { runTest("plugins/uast-kotlin-fir/testData/type/unresolved.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 53232b18252..d3327b50c0c 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("typeCheck.kt") + public void testTypeCheck() throws Exception { + runTest("plugins/uast-kotlin-fir/testData/type/typeCheck.kt"); + } + @TestMetadata("unresolved.kt") public void testUnresolved() throws Exception { runTest("plugins/uast-kotlin-fir/testData/type/unresolved.kt"); diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUTypeCheckExpression.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUTypeCheckExpression.kt deleted file mode 100644 index 04e68958488..00000000000 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUTypeCheckExpression.kt +++ /dev/null @@ -1,41 +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 org.jetbrains.kotlin.psi.KtIsExpression -import org.jetbrains.uast.UBinaryExpressionWithType -import org.jetbrains.uast.UElement -import org.jetbrains.uast.UastBinaryExpressionWithTypeKind - -class KotlinUTypeCheckExpression( - override val sourcePsi: KtIsExpression, - givenParent: UElement? -) : KotlinAbstractUExpression(givenParent), UBinaryExpressionWithType, KotlinUElementWithType, KotlinEvaluatableUElement { - override val operand by lz { KotlinConverter.convertOrEmpty(sourcePsi.leftHandSide, this) } - - override val type by lz { sourcePsi.typeReference.toPsiType(this) } - - override val typeReference = sourcePsi.typeReference?.let { - KotlinUTypeReferenceExpression(it, this) { it.toPsiType(this) } - } - - override val operationKind = - if(sourcePsi.isNegated) - KotlinBinaryExpressionWithTypeKinds.NEGATED_INSTANCE_CHECK - else - UastBinaryExpressionWithTypeKind.INSTANCE_CHECK -}