From f85ebe7f43b287eec491d4710222b6a0417156d1 Mon Sep 17 00:00:00 2001 From: Nicolay Mitropolsky Date: Tue, 2 Jul 2019 21:24:42 +0300 Subject: [PATCH] Uast: implicit returns for lambda expressions (KT-32370) --- .../uast/kotlin/KotlinAbstractUElement.kt | 4 + .../uast/kotlin/KotlinAbstractUElement.kt.183 | 4 + .../uast/kotlin/KotlinUastLanguagePlugin.kt | 10 +- .../kotlin/KotlinUastLanguagePlugin.kt.182 | 10 +- .../kotlin/KotlinUastLanguagePlugin.kt.183 | 10 +- .../kotlin/declarations/KotlinUVariable.kt | 1 + .../expressions/KotlinUBlockExpression.kt | 2 +- .../expressions/KotlinULambdaExpression.kt | 36 +++++-- plugins/uast-kotlin/testData/Delegate.log.txt | 26 ++--- .../uast-kotlin/testData/Delegate.render.txt | 4 +- .../uast-kotlin/testData/Delegate.values.txt | 38 ++++---- plugins/uast-kotlin/testData/LambdaReturn.kt | 43 +++++++++ .../uast-kotlin/testData/LambdaReturn.log.txt | 96 +++++++++++++++++++ .../testData/LambdaReturn.render.txt | 33 +++++++ plugins/uast-kotlin/testData/Lambdas.log.txt | 11 ++- .../uast-kotlin/testData/Lambdas.render.txt | 2 +- .../testData/PropertyDelegate.log.txt | 13 ++- .../testData/TypeReferences.log.txt | 11 ++- .../testData/TypeReferences.render.txt | 2 +- .../testData/TypeReferences.resolved.txt | 2 +- .../UnexpectedContainerException.log.txt | 25 ++--- .../UnexpectedContainerException.render.txt | 2 +- .../UnexpectedContainerException.types.txt | 27 +++--- .../tests/SimpleKotlinRenderLogTest.kt | 3 + .../tests/SimpleKotlinRenderLogTest.kt.183 | 3 + 25 files changed, 332 insertions(+), 86 deletions(-) create mode 100644 plugins/uast-kotlin/testData/LambdaReturn.kt create mode 100644 plugins/uast-kotlin/testData/LambdaReturn.log.txt create mode 100644 plugins/uast-kotlin/testData/LambdaReturn.render.txt diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinAbstractUElement.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinAbstractUElement.kt index e32508533e7..45e0f671a39 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinAbstractUElement.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinAbstractUElement.kt @@ -199,6 +199,10 @@ fun doConvertParent(element: UElement, parent: PsiElement?): UElement? { }).expressions.single() } + if (result is KotlinULambdaExpression.Body && element is UExpression && result.implicitReturn?.returnExpression == element) { + return result.implicitReturn!! + } + return result } diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinAbstractUElement.kt.183 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinAbstractUElement.kt.183 index 8e32b0d66bf..a1f5d4a703c 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinAbstractUElement.kt.183 +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinAbstractUElement.kt.183 @@ -195,6 +195,10 @@ fun doConvertParent(element: UElement, parent: PsiElement?): UElement? { }).expressions.single() } + if (result is KotlinULambdaExpression.Body && element is UExpression && result.implicitReturn?.returnExpression == element) { + return result.implicitReturn!! + } + return result } diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt index 09ffb61f61b..4d1fb9e423c 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt @@ -376,7 +376,15 @@ internal object KotlinConverter { is KtContinueExpression -> expr(build(::KotlinUContinueExpression)) is KtReturnExpression -> expr(build(::KotlinUReturnExpression)) is KtThrowExpression -> expr(build(::KotlinUThrowExpression)) - is KtBlockExpression -> expr(build(::KotlinUBlockExpression)) + is KtBlockExpression -> expr { + if (expression.parent is KtFunctionLiteral + && expression.parent.parent is KtLambdaExpression + && givenParent !is KotlinULambdaExpression + ) { + KotlinULambdaExpression(expression.parent.parent as KtLambdaExpression, givenParent).body + } else + KotlinUBlockExpression(expression, givenParent) + } is KtConstantExpression -> expr(build(::KotlinULiteralExpression)) is KtTryExpression -> expr(build(::KotlinUTryExpression)) is KtArrayAccessExpression -> expr(build(::KotlinUArrayAccessExpression)) diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt.182 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt.182 index 0c9461ab2af..5815dc05832 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt.182 +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt.182 @@ -333,7 +333,15 @@ internal object KotlinConverter { is KtContinueExpression -> expr(build(::KotlinUContinueExpression)) is KtReturnExpression -> expr(build(::KotlinUReturnExpression)) is KtThrowExpression -> expr(build(::KotlinUThrowExpression)) - is KtBlockExpression -> expr(build(::KotlinUBlockExpression)) + is KtBlockExpression -> expr { + if (expression.parent is KtFunctionLiteral + && expression.parent.parent is KtLambdaExpression + && givenParent !is KotlinULambdaExpression + ) { + KotlinULambdaExpression(expression.parent.parent as KtLambdaExpression, givenParent).body + } else + KotlinUBlockExpression(expression, givenParent) + } is KtConstantExpression -> expr(build(::KotlinULiteralExpression)) is KtTryExpression -> expr(build(::KotlinUTryExpression)) is KtArrayAccessExpression -> expr(build(::KotlinUArrayAccessExpression)) diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt.183 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt.183 index 70bbda4b3c3..79f1831e606 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt.183 +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt.183 @@ -335,7 +335,15 @@ internal object KotlinConverter { is KtContinueExpression -> expr(build(::KotlinUContinueExpression)) is KtReturnExpression -> expr(build(::KotlinUReturnExpression)) is KtThrowExpression -> expr(build(::KotlinUThrowExpression)) - is KtBlockExpression -> expr(build(::KotlinUBlockExpression)) + is KtBlockExpression -> expr { + if (expression.parent is KtFunctionLiteral + && expression.parent.parent is KtLambdaExpression + && givenParent !is KotlinULambdaExpression + ) { + KotlinULambdaExpression(expression.parent.parent as KtLambdaExpression, givenParent).body + } else + KotlinUBlockExpression(expression, givenParent) + } is KtConstantExpression -> expr(build(::KotlinULiteralExpression)) is KtTryExpression -> expr(build(::KotlinUTryExpression)) is KtArrayAccessExpression -> expr(build(::KotlinUArrayAccessExpression)) diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUVariable.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUVariable.kt index 70012081bcd..842415d826a 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUVariable.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUVariable.kt @@ -110,6 +110,7 @@ abstract class AbstractKotlinUVariable(givenParent: UElement?) : KotlinAbstractU is KtNameReferenceExpression -> sourcePsi.getReferencedNameElement() is KtBinaryExpression, is KtCallExpression -> null // e.g. `foo("Lorem ipsum") ?: foo("dolor sit amet")` is KtDestructuringDeclaration -> sourcePsi.valOrVarKeyword + is KtLambdaExpression -> sourcePsi.functionLiteral.lBrace else -> sourcePsi } ?: return null return KotlinUIdentifier(nameIdentifier, identifierSourcePsi, this) diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUBlockExpression.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUBlockExpression.kt index ab0f06f0819..3313745d1e4 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUBlockExpression.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUBlockExpression.kt @@ -21,7 +21,7 @@ import org.jetbrains.kotlin.psi.KtAnonymousInitializer import org.jetbrains.kotlin.psi.KtBlockExpression import org.jetbrains.uast.* -class KotlinUBlockExpression( +open class KotlinUBlockExpression( override val sourcePsi: KtBlockExpression, givenParent: UElement? ) : KotlinAbstractUExpression(givenParent), UBlockExpression, KotlinUElementWithType { diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinULambdaExpression.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinULambdaExpression.kt index 86b53dab6c6..8dfc837d241 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinULambdaExpression.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinULambdaExpression.kt @@ -17,12 +17,12 @@ package org.jetbrains.uast.kotlin import com.intellij.psi.PsiType +import org.jetbrains.kotlin.psi.KtBlockExpression +import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.KtLambdaExpression -import org.jetbrains.uast.UBlockExpression -import org.jetbrains.uast.UElement -import org.jetbrains.uast.ULambdaExpression +import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsResultOfLambda +import org.jetbrains.uast.* import org.jetbrains.uast.kotlin.psi.UastKotlinPsiParameter -import org.jetbrains.uast.withMargin class KotlinULambdaExpression( override val sourcePsi: KtLambdaExpression, @@ -31,8 +31,32 @@ class KotlinULambdaExpression( override val functionalInterfaceType: PsiType? get() = getFunctionalInterfaceType() - override val body by lz { KotlinConverter.convertOrEmpty(sourcePsi.bodyExpression, this) } - + override val body by lz { + sourcePsi.bodyExpression?.let { Body(it, this) } ?: UastEmptyExpression(this) + } + + class Body(bodyExpression: KtBlockExpression, parent: KotlinULambdaExpression) : KotlinUBlockExpression(bodyExpression, parent) { + + override val expressions: List by lz expressions@{ + val statements = sourcePsi.statements + if (statements.isEmpty()) return@expressions emptyList() + ArrayList(statements.size).also { result -> + statements.subList(0, statements.size - 1).mapTo(result) { KotlinConverter.convertOrEmpty(it, this) } + result.add(implicitReturn ?: KotlinConverter.convertOrEmpty(statements.last(), this)) + } + } + + val implicitReturn: KotlinUImplicitReturnExpression? by lz { + val lastExpression = sourcePsi.statements.lastOrNull() ?: return@lz null + if (!lastExpression.isUsedAsResultOfLambda(lastExpression.analyze())) return@lz null + + KotlinUImplicitReturnExpression(this).apply { + returnExpression = KotlinConverter.convertOrEmpty(lastExpression, this) + } + } + + } + override val valueParameters by lz { sourcePsi.valueParameters.mapIndexed { i, p -> KotlinUParameter(UastKotlinPsiParameter.create(p, sourcePsi, this, i), sourcePsi, this) diff --git a/plugins/uast-kotlin/testData/Delegate.log.txt b/plugins/uast-kotlin/testData/Delegate.log.txt index 212c16989e1..42cd7abe2e0 100644 --- a/plugins/uast-kotlin/testData/Delegate.log.txt +++ b/plugins/uast-kotlin/testData/Delegate.log.txt @@ -24,12 +24,13 @@ UFile (package = ) USimpleNameReferenceExpression (identifier = lazy, resolvesTo = null) ULambdaExpression UBlockExpression - UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 3)) - UIdentifier (Identifier (MyColor)) - USimpleNameReferenceExpression (identifier = , resolvesTo = MyColor) - ULiteralExpression (value = 18) - ULiteralExpression (value = 2) - ULiteralExpression (value = 3) + UReturnExpression + UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 3)) + UIdentifier (Identifier (MyColor)) + USimpleNameReferenceExpression (identifier = , resolvesTo = MyColor) + ULiteralExpression (value = 18) + ULiteralExpression (value = 2) + ULiteralExpression (value = 3) UField (name = lambda) UAnnotation (fqName = org.jetbrains.annotations.NotNull) UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1)) @@ -37,12 +38,13 @@ UFile (package = ) USimpleNameReferenceExpression (identifier = lazy, resolvesTo = null) ULambdaExpression UBlockExpression - UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 3)) - UIdentifier (Identifier (MyColor)) - USimpleNameReferenceExpression (identifier = , resolvesTo = MyColor) - ULiteralExpression (value = 1) - ULiteralExpression (value = 2) - ULiteralExpression (value = 3) + UReturnExpression + UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 3)) + UIdentifier (Identifier (MyColor)) + USimpleNameReferenceExpression (identifier = , resolvesTo = MyColor) + ULiteralExpression (value = 1) + ULiteralExpression (value = 2) + ULiteralExpression (value = 3) UField (name = nonLazy) UAnnotation (fqName = org.jetbrains.annotations.NotNull) UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 3)) diff --git a/plugins/uast-kotlin/testData/Delegate.render.txt b/plugins/uast-kotlin/testData/Delegate.render.txt index 4200b574aab..0b50ead54f0 100644 --- a/plugins/uast-kotlin/testData/Delegate.render.txt +++ b/plugins/uast-kotlin/testData/Delegate.render.txt @@ -10,8 +10,8 @@ public final class MyColor { public final class Some { @org.jetbrains.annotations.NotNull private final var delegate$delegate: kotlin.Lazy - @org.jetbrains.annotations.NotNull private final var lambda: kotlin.Lazy = lazy({ - (1, 2, 3) + @org.jetbrains.annotations.NotNull private final var lambda: kotlin.Lazy = lazy({ + return (1, 2, 3) }) @org.jetbrains.annotations.NotNull private final var nonLazy: MyColor = (1, 2, 3) public final fun getDelegate() : MyColor = UastEmptyExpression diff --git a/plugins/uast-kotlin/testData/Delegate.values.txt b/plugins/uast-kotlin/testData/Delegate.values.txt index 6ede03a51d2..90e8a9d44bb 100644 --- a/plugins/uast-kotlin/testData/Delegate.values.txt +++ b/plugins/uast-kotlin/testData/Delegate.values.txt @@ -20,37 +20,39 @@ UFile (package = ) [public final class MyColor {...] UField (name = delegate$delegate) [@org.jetbrains.annotations.NotNull private final var delegate$delegate: kotlin.Lazy] UAnnotation (fqName = org.jetbrains.annotations.NotNull) [@org.jetbrains.annotations.NotNull] UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1)) [lazy({ ...})] = external lazy({ - (18, 2, 3) + return (18, 2, 3) })(Undetermined) UIdentifier (Identifier (lazy)) [UIdentifier (Identifier (lazy))] USimpleNameReferenceExpression (identifier = lazy, resolvesTo = null) [lazy] = external lazy({ - (18, 2, 3) + return (18, 2, 3) })(Undetermined) ULambdaExpression [{ ...}] = Undetermined - UBlockExpression [{...}] = external (18, 2, 3)(18, 2, 3) - UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 3)) [(18, 2, 3)] = external (18, 2, 3)(18, 2, 3) - UIdentifier (Identifier (MyColor)) [UIdentifier (Identifier (MyColor))] - USimpleNameReferenceExpression (identifier = , resolvesTo = MyColor) [] = external (18, 2, 3)(18, 2, 3) - ULiteralExpression (value = 18) [18] = 18 - ULiteralExpression (value = 2) [2] = 2 - ULiteralExpression (value = 3) [3] = 3 + UBlockExpression [{...}] = Nothing + UReturnExpression [return (18, 2, 3)] = Nothing + UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 3)) [(18, 2, 3)] = external (18, 2, 3)(18, 2, 3) + UIdentifier (Identifier (MyColor)) [UIdentifier (Identifier (MyColor))] + USimpleNameReferenceExpression (identifier = , resolvesTo = MyColor) [] = external (18, 2, 3)(18, 2, 3) + ULiteralExpression (value = 18) [18] = 18 + ULiteralExpression (value = 2) [2] = 2 + ULiteralExpression (value = 3) [3] = 3 UField (name = lambda) [@org.jetbrains.annotations.NotNull private final var lambda: kotlin.Lazy = lazy({ ...})] UAnnotation (fqName = org.jetbrains.annotations.NotNull) [@org.jetbrains.annotations.NotNull] UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1)) [lazy({ ...})] = external lazy({ - (1, 2, 3) + return (1, 2, 3) })(Undetermined) UIdentifier (Identifier (lazy)) [UIdentifier (Identifier (lazy))] USimpleNameReferenceExpression (identifier = lazy, resolvesTo = null) [lazy] = external lazy({ - (1, 2, 3) + return (1, 2, 3) })(Undetermined) ULambdaExpression [{ ...}] = Undetermined - UBlockExpression [{...}] = external (1, 2, 3)(1, 2, 3) - UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 3)) [(1, 2, 3)] = external (1, 2, 3)(1, 2, 3) - UIdentifier (Identifier (MyColor)) [UIdentifier (Identifier (MyColor))] - USimpleNameReferenceExpression (identifier = , resolvesTo = MyColor) [] = external (1, 2, 3)(1, 2, 3) - ULiteralExpression (value = 1) [1] = 1 - ULiteralExpression (value = 2) [2] = 2 - ULiteralExpression (value = 3) [3] = 3 + UBlockExpression [{...}] = Nothing + UReturnExpression [return (1, 2, 3)] = Nothing + UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 3)) [(1, 2, 3)] = external (1, 2, 3)(1, 2, 3) + UIdentifier (Identifier (MyColor)) [UIdentifier (Identifier (MyColor))] + USimpleNameReferenceExpression (identifier = , resolvesTo = MyColor) [] = external (1, 2, 3)(1, 2, 3) + ULiteralExpression (value = 1) [1] = 1 + ULiteralExpression (value = 2) [2] = 2 + ULiteralExpression (value = 3) [3] = 3 UField (name = nonLazy) [@org.jetbrains.annotations.NotNull private final var nonLazy: MyColor = (1, 2, 3)] UAnnotation (fqName = org.jetbrains.annotations.NotNull) [@org.jetbrains.annotations.NotNull] UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 3)) [(1, 2, 3)] = external (1, 2, 3)(1, 2, 3) diff --git a/plugins/uast-kotlin/testData/LambdaReturn.kt b/plugins/uast-kotlin/testData/LambdaReturn.kt new file mode 100644 index 00000000000..6b2d9caa926 --- /dev/null +++ b/plugins/uast-kotlin/testData/LambdaReturn.kt @@ -0,0 +1,43 @@ +package org.jetbrains.uast.kotlin + +fun foo() { + + val lam1 = { a: Int -> + val b = 1 + a + b + } + + val lam2 = { a: Int -> + val c = 1 + if (a > 0) + a + c + else + a - c + } + + val lam3 = lbd@{ a: Int -> + val d = 1 + return@lbd a + d + } + + val lam4 = fun(a: Int): String { + if (a < 5) return "5" + + if (a > 0) + return "1" + else + return "2" + } + + + bar { + if (it > 5) return + val b = 1 + it + b + } + +} + +private inline fun bar(lmbd: (Int) -> Int) { + lmbd(1) +} \ No newline at end of file diff --git a/plugins/uast-kotlin/testData/LambdaReturn.log.txt b/plugins/uast-kotlin/testData/LambdaReturn.log.txt new file mode 100644 index 00000000000..78d672dc311 --- /dev/null +++ b/plugins/uast-kotlin/testData/LambdaReturn.log.txt @@ -0,0 +1,96 @@ +UFile (package = org.jetbrains.uast.kotlin) + UClass (name = LambdaReturnKt) + UAnnotationMethod (name = foo) + UBlockExpression + UDeclarationsExpression + ULocalVariable (name = lam1) + ULambdaExpression + UParameter (name = a) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UBlockExpression + UDeclarationsExpression + ULocalVariable (name = b) + ULiteralExpression (value = 1) + UReturnExpression + UBinaryExpression (operator = +) + USimpleNameReferenceExpression (identifier = a) + USimpleNameReferenceExpression (identifier = b) + UDeclarationsExpression + ULocalVariable (name = lam2) + ULambdaExpression + UParameter (name = a) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UBlockExpression + UDeclarationsExpression + ULocalVariable (name = c) + ULiteralExpression (value = 1) + UReturnExpression + UIfExpression + UBinaryExpression (operator = >) + USimpleNameReferenceExpression (identifier = a) + ULiteralExpression (value = 0) + UBinaryExpression (operator = +) + USimpleNameReferenceExpression (identifier = a) + USimpleNameReferenceExpression (identifier = c) + UBinaryExpression (operator = -) + USimpleNameReferenceExpression (identifier = a) + USimpleNameReferenceExpression (identifier = c) + UDeclarationsExpression + ULocalVariable (name = lam3) + ULabeledExpression (label = lbd) + ULambdaExpression + UParameter (name = a) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UBlockExpression + UDeclarationsExpression + ULocalVariable (name = d) + ULiteralExpression (value = 1) + UReturnExpression + UBinaryExpression (operator = +) + USimpleNameReferenceExpression (identifier = a) + USimpleNameReferenceExpression (identifier = d) + UDeclarationsExpression + ULocalVariable (name = lam4) + ULambdaExpression + UParameter (name = a) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UBlockExpression + UIfExpression + UBinaryExpression (operator = <) + USimpleNameReferenceExpression (identifier = a) + ULiteralExpression (value = 5) + UReturnExpression + ULiteralExpression (value = "5") + UIfExpression + UBinaryExpression (operator = >) + USimpleNameReferenceExpression (identifier = a) + ULiteralExpression (value = 0) + UReturnExpression + ULiteralExpression (value = "1") + UReturnExpression + ULiteralExpression (value = "2") + UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1)) + UIdentifier (Identifier (bar)) + USimpleNameReferenceExpression (identifier = bar, resolvesTo = null) + ULambdaExpression + UBlockExpression + UIfExpression + UBinaryExpression (operator = >) + USimpleNameReferenceExpression (identifier = it) + ULiteralExpression (value = 5) + UReturnExpression + UDeclarationsExpression + ULocalVariable (name = b) + ULiteralExpression (value = 1) + UReturnExpression + UBinaryExpression (operator = +) + USimpleNameReferenceExpression (identifier = it) + USimpleNameReferenceExpression (identifier = b) + UAnnotationMethod (name = bar) + UParameter (name = lmbd) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UBlockExpression + UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1)) + UIdentifier (Identifier (lmbd)) + USimpleNameReferenceExpression (identifier = invoke, resolvesTo = null) + ULiteralExpression (value = 1) diff --git a/plugins/uast-kotlin/testData/LambdaReturn.render.txt b/plugins/uast-kotlin/testData/LambdaReturn.render.txt new file mode 100644 index 00000000000..7bd2eb75ab9 --- /dev/null +++ b/plugins/uast-kotlin/testData/LambdaReturn.render.txt @@ -0,0 +1,33 @@ +package org.jetbrains.uast.kotlin + +public final class LambdaReturnKt { + public static final fun foo() : void { + var lam1: kotlin.jvm.functions.Function1 = { @org.jetbrains.annotations.NotNull var a: int -> + + var b: int = 1 + return a + b + } + var lam2: kotlin.jvm.functions.Function1 = { @org.jetbrains.annotations.NotNull var a: int -> + + var c: int = 1 + return if (a > 0) a + c else a - c + } + var lam3: kotlin.jvm.functions.Function1 = lbd@ { @org.jetbrains.annotations.NotNull var a: int -> + + var d: int = 1 + return a + d + } + var lam4: kotlin.jvm.functions.Function1 = fun (@org.jetbrains.annotations.NotNull var a: int) { + if (a < 5) return "5" + if (a > 0) return "1" else return "2" + } + bar({ + if (it > 5) return + var b: int = 1 + return it + b + }) + } + private static final fun bar(@org.jetbrains.annotations.NotNull lmbd: kotlin.jvm.functions.Function1) : void { + invoke(1) + } +} diff --git a/plugins/uast-kotlin/testData/Lambdas.log.txt b/plugins/uast-kotlin/testData/Lambdas.log.txt index eb35b4d0a30..b87a97a8480 100644 --- a/plugins/uast-kotlin/testData/Lambdas.log.txt +++ b/plugins/uast-kotlin/testData/Lambdas.log.txt @@ -14,11 +14,12 @@ UFile (package = ) USimpleNameReferenceExpression (identifier = filter, resolvesTo = null) ULambdaExpression UBlockExpression - UQualifiedReferenceExpression - USimpleNameReferenceExpression (identifier = it) - UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0)) - UIdentifier (Identifier (isEmpty)) - USimpleNameReferenceExpression (identifier = isEmpty, resolvesTo = null) + UReturnExpression + UQualifiedReferenceExpression + USimpleNameReferenceExpression (identifier = it) + UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0)) + UIdentifier (Identifier (isEmpty)) + USimpleNameReferenceExpression (identifier = isEmpty, resolvesTo = null) UAnnotationMethod (name = doSelectItem) UParameter (name = selectItemFunction) UAnnotation (fqName = org.jetbrains.annotations.NotNull) diff --git a/plugins/uast-kotlin/testData/Lambdas.render.txt b/plugins/uast-kotlin/testData/Lambdas.render.txt index 5a53e1579bd..7112bc0d0ba 100644 --- a/plugins/uast-kotlin/testData/Lambdas.render.txt +++ b/plugins/uast-kotlin/testData/Lambdas.render.txt @@ -3,7 +3,7 @@ import java.util.stream.Stream public final class LambdasKt { public static final fun foo() : void { Stream.empty().filter({ - it.isEmpty() + return it.isEmpty() }) } public static final fun doSelectItem(@org.jetbrains.annotations.NotNull selectItemFunction: kotlin.jvm.functions.Function0) : void { diff --git a/plugins/uast-kotlin/testData/PropertyDelegate.log.txt b/plugins/uast-kotlin/testData/PropertyDelegate.log.txt index 70f773d3477..7fe13b894f3 100644 --- a/plugins/uast-kotlin/testData/PropertyDelegate.log.txt +++ b/plugins/uast-kotlin/testData/PropertyDelegate.log.txt @@ -7,7 +7,8 @@ UFile (package = ) USimpleNameReferenceExpression (identifier = lazy, resolvesTo = null) ULambdaExpression UBlockExpression - ULiteralExpression (value = "/sdcard") + UReturnExpression + ULiteralExpression (value = "/sdcard") UField (name = annotatedDelegate$delegate) UAnnotation (fqName = org.jetbrains.annotations.NotNull) UAnnotation (fqName = kotlin.Suppress) @@ -16,9 +17,10 @@ UFile (package = ) USimpleNameReferenceExpression (identifier = lazy, resolvesTo = null) ULambdaExpression UBlockExpression - UBinaryExpression (operator = +) - ULiteralExpression (value = 1) - ULiteralExpression (value = 1) + UReturnExpression + UBinaryExpression (operator = +) + ULiteralExpression (value = 1) + ULiteralExpression (value = 1) UAnnotationMethod (name = getSdCardPath) UAnnotationMethod (name = localPropertyTest) UBlockExpression @@ -29,5 +31,6 @@ UFile (package = ) USimpleNameReferenceExpression (identifier = lazy, resolvesTo = null) ULambdaExpression UBlockExpression - ULiteralExpression (value = "/sdcard") + UReturnExpression + ULiteralExpression (value = "/sdcard") UAnnotationMethod (name = getAnnotatedDelegate) diff --git a/plugins/uast-kotlin/testData/TypeReferences.log.txt b/plugins/uast-kotlin/testData/TypeReferences.log.txt index 3409cf0f55c..1cffd3a1b49 100644 --- a/plugins/uast-kotlin/testData/TypeReferences.log.txt +++ b/plugins/uast-kotlin/testData/TypeReferences.log.txt @@ -52,11 +52,12 @@ UFile (package = ) USimpleNameReferenceExpression (identifier = map, resolvesTo = null) ULambdaExpression UBlockExpression - UQualifiedReferenceExpression - USimpleNameReferenceExpression (identifier = it) - UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0)) - UIdentifier (Identifier (toString)) - USimpleNameReferenceExpression (identifier = toString, resolvesTo = null) + UReturnExpression + UQualifiedReferenceExpression + USimpleNameReferenceExpression (identifier = it) + UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0)) + UIdentifier (Identifier (toString)) + USimpleNameReferenceExpression (identifier = toString, resolvesTo = null) UDeclarationsExpression ULocalVariable (name = lls) UDeclarationsExpression diff --git a/plugins/uast-kotlin/testData/TypeReferences.render.txt b/plugins/uast-kotlin/testData/TypeReferences.render.txt index d5037fdf807..2e7724af469 100644 --- a/plugins/uast-kotlin/testData/TypeReferences.render.txt +++ b/plugins/uast-kotlin/testData/TypeReferences.render.txt @@ -13,7 +13,7 @@ public final class TypeReferencesKt { } var tl: java.util.List = listOf(at) var tsl: java.util.List = tl.map({ - it.toString() + return it.toString() }) var lls: java.util.List> var llsAliased: java.util.List> diff --git a/plugins/uast-kotlin/testData/TypeReferences.resolved.txt b/plugins/uast-kotlin/testData/TypeReferences.resolved.txt index 7d211df548f..eeaaf17f643 100644 --- a/plugins/uast-kotlin/testData/TypeReferences.resolved.txt +++ b/plugins/uast-kotlin/testData/TypeReferences.resolved.txt @@ -22,7 +22,7 @@ UTypeReferenceExpression (name = T) -> USimpleNameReferenceExpression (identifie ULocalVariable (name = tsl) -> UQualifiedReferenceExpression -> null: null UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = tl) -> LightVariableBuilder:tl: tl UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1)) -> USimpleNameReferenceExpression (identifier = map) -> PsiMethod:map: map - UBlockExpression -> UQualifiedReferenceExpression -> null: null + UReturnExpression -> UQualifiedReferenceExpression -> null: null UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = it) -> null: null UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0)) -> USimpleNameReferenceExpression (identifier = toString) -> null: null UTypeReferenceExpression (name = java.util.List>) -> USimpleNameReferenceExpression (identifier = List) -> PsiClass:List: List diff --git a/plugins/uast-kotlin/testData/UnexpectedContainerException.log.txt b/plugins/uast-kotlin/testData/UnexpectedContainerException.log.txt index d86f0885bcf..68b70cbe286 100644 --- a/plugins/uast-kotlin/testData/UnexpectedContainerException.log.txt +++ b/plugins/uast-kotlin/testData/UnexpectedContainerException.log.txt @@ -25,15 +25,16 @@ UFile (package = ) USimpleNameReferenceExpression (identifier = java) ULambdaExpression UBlockExpression - UObjectLiteralExpression - UClass (name = null) - UAnnotationMethod (name = onError) - UParameter (name = throwable) - UAnnotation (fqName = org.jetbrains.annotations.NotNull) - UBlockExpression - UThrowExpression - UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 1)) - UIdentifier (Identifier (UnsupportedOperationException)) - USimpleNameReferenceExpression (identifier = , resolvesTo = UnsupportedOperationException) - ULiteralExpression (value = "") - UAnnotationMethod (name = Model$1$1) + UReturnExpression + UObjectLiteralExpression + UClass (name = null) + UAnnotationMethod (name = onError) + UParameter (name = throwable) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UBlockExpression + UThrowExpression + UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 1)) + UIdentifier (Identifier (UnsupportedOperationException)) + USimpleNameReferenceExpression (identifier = , resolvesTo = UnsupportedOperationException) + ULiteralExpression (value = "") + UAnnotationMethod (name = Model$1$1) diff --git a/plugins/uast-kotlin/testData/UnexpectedContainerException.render.txt b/plugins/uast-kotlin/testData/UnexpectedContainerException.render.txt index cb4745abfd8..2dce43115b2 100644 --- a/plugins/uast-kotlin/testData/UnexpectedContainerException.render.txt +++ b/plugins/uast-kotlin/testData/UnexpectedContainerException.render.txt @@ -9,7 +9,7 @@ public final class Model { public fun Model() { { crashMe(Callback.java, { - anonymous object : Callback { + return anonymous object : Callback { override fun onError(throwable: Throwable) { throw UnsupportedOperationException("") } diff --git a/plugins/uast-kotlin/testData/UnexpectedContainerException.types.txt b/plugins/uast-kotlin/testData/UnexpectedContainerException.types.txt index 5f1d304391c..88a701c1009 100644 --- a/plugins/uast-kotlin/testData/UnexpectedContainerException.types.txt +++ b/plugins/uast-kotlin/testData/UnexpectedContainerException.types.txt @@ -23,17 +23,18 @@ UFile (package = ) [public abstract interface Callback {...] UQualifiedReferenceExpression [Callback.java] : PsiType:Class UClassLiteralExpression [Callback] : PsiType:KClass USimpleNameReferenceExpression (identifier = java) [java] : PsiType:Class - ULambdaExpression [{ ...}] : PsiType: + ULambdaExpression [{ ...}] : PsiType:Function0 UBlockExpression [{...}] - UObjectLiteralExpression [anonymous object : Callback {... }] : PsiType:Callback - UClass (name = null) [final class null : Callback {...}] - UAnnotationMethod (name = onError) [public fun onError(@org.jetbrains.annotations.NotNull throwable: java.lang.Throwable) : void {...}] - UParameter (name = throwable) [@org.jetbrains.annotations.NotNull var throwable: java.lang.Throwable] - UAnnotation (fqName = org.jetbrains.annotations.NotNull) [@org.jetbrains.annotations.NotNull] - UBlockExpression [{...}] : PsiType:Void - UThrowExpression [throw ("")] : PsiType:Void - UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 1)) [("")] : PsiType:UnsupportedOperationException - UIdentifier (Identifier (UnsupportedOperationException)) [UIdentifier (Identifier (UnsupportedOperationException))] - USimpleNameReferenceExpression (identifier = , resolvesTo = UnsupportedOperationException) [] : PsiType:UnsupportedOperationException - ULiteralExpression (value = "") [""] : PsiType:String - UAnnotationMethod (name = Model$1$1) [fun Model$1$1() = UastEmptyExpression] + UReturnExpression [return anonymous object : Callback {... }] + UObjectLiteralExpression [anonymous object : Callback {... }] : PsiType:Callback + UClass (name = null) [final class null : Callback {...}] + UAnnotationMethod (name = onError) [public fun onError(@org.jetbrains.annotations.NotNull throwable: java.lang.Throwable) : void {...}] + UParameter (name = throwable) [@org.jetbrains.annotations.NotNull var throwable: java.lang.Throwable] + UAnnotation (fqName = org.jetbrains.annotations.NotNull) [@org.jetbrains.annotations.NotNull] + UBlockExpression [{...}] : PsiType:Void + UThrowExpression [throw ("")] : PsiType:Void + UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 1)) [("")] : PsiType:UnsupportedOperationException + UIdentifier (Identifier (UnsupportedOperationException)) [UIdentifier (Identifier (UnsupportedOperationException))] + USimpleNameReferenceExpression (identifier = , resolvesTo = UnsupportedOperationException) [] : PsiType:UnsupportedOperationException + ULiteralExpression (value = "") [""] : PsiType:String + UAnnotationMethod (name = Model$1$1) [fun Model$1$1() = UastEmptyExpression] diff --git a/plugins/uast-kotlin/tests/SimpleKotlinRenderLogTest.kt b/plugins/uast-kotlin/tests/SimpleKotlinRenderLogTest.kt index 4e27b5cee53..66162a228ca 100644 --- a/plugins/uast-kotlin/tests/SimpleKotlinRenderLogTest.kt +++ b/plugins/uast-kotlin/tests/SimpleKotlinRenderLogTest.kt @@ -99,6 +99,9 @@ class SimpleKotlinRenderLogTest : AbstractKotlinRenderLogTest() { @Test fun testConstructorDelegate() = doTest("ConstructorDelegate") + + @Test + fun testLambdaReturn() = doTest("LambdaReturn") } fun withForceUInjectionHostValue(call: () -> Unit) { diff --git a/plugins/uast-kotlin/tests/SimpleKotlinRenderLogTest.kt.183 b/plugins/uast-kotlin/tests/SimpleKotlinRenderLogTest.kt.183 index 6a7e6f453da..8710639fd67 100644 --- a/plugins/uast-kotlin/tests/SimpleKotlinRenderLogTest.kt.183 +++ b/plugins/uast-kotlin/tests/SimpleKotlinRenderLogTest.kt.183 @@ -93,4 +93,7 @@ class SimpleKotlinRenderLogTest : AbstractKotlinRenderLogTest() { @Test fun testConstructorDelegate() = doTest("ConstructorDelegate") + + @Test + fun testLambdaReturn() = doTest("LambdaReturn") }