diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUVariable.kt.181 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUVariable.kt.181 index 95d31bdd079..fe52b4ba6b1 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUVariable.kt.181 +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUVariable.kt.181 @@ -380,7 +380,7 @@ class KotlinUEnumConstant( psi: PsiEnumConstant, override val sourcePsi: KtElement?, givenParent: UElement? -) : AbstractKotlinUVariable(givenParent), UEnumConstant, PsiEnumConstant by psi { +) : AbstractKotlinUVariable(givenParent), UEnumConstant, UCallExpressionEx, PsiEnumConstant by psi { override val initializingClass: UClass? by lz { (psi.initializingClass as? KtLightClass)?.let { initializingClass -> @@ -458,4 +458,7 @@ class KotlinUEnumConstant( override val identifier: String get() = psi.containingClass?.name ?: "" } + + override fun getArgumentForParameter(i: Int): UExpression? = valueArguments.getOrNull(i) + } \ No newline at end of file diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUCollectionLiteralExpression.kt.181 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUCollectionLiteralExpression.kt.181 new file mode 100644 index 00000000000..f0d59284ab6 --- /dev/null +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUCollectionLiteralExpression.kt.181 @@ -0,0 +1,56 @@ +/* + * Copyright 2000-2018 JetBrains s.r.o. 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.expressions + +import com.intellij.psi.PsiArrayType +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiMethod +import com.intellij.psi.PsiType +import org.jetbrains.kotlin.psi.KtCollectionLiteralExpression +import org.jetbrains.uast.* +import org.jetbrains.uast.kotlin.KotlinAbstractUExpression +import org.jetbrains.uast.kotlin.KotlinConverter +import org.jetbrains.uast.kotlin.KotlinUElementWithType + +class KotlinUCollectionLiteralExpression( + override val sourcePsi: KtCollectionLiteralExpression, + givenParent: UElement? +) : KotlinAbstractUExpression(givenParent), UCallExpressionEx, KotlinUElementWithType { + + override val classReference: UReferenceExpression? get() = null + + override val kind: UastCallKind = UastCallKind.NESTED_ARRAY_INITIALIZER + + override val methodIdentifier: UIdentifier? by lazy { UIdentifier(sourcePsi.leftBracket, this) } + + override val methodName: String? get() = null + + override val receiver: UExpression? get() = null + + override val receiverType: PsiType? get() = null + + override val returnType: PsiType? get() = getExpressionType() + + override val typeArgumentCount: Int get() = typeArguments.size + + override val typeArguments: List get() = listOfNotNull((returnType as? PsiArrayType)?.componentType) + + override val valueArgumentCount: Int + get() = sourcePsi.getInnerExpressions().size + + override val valueArguments by lazy { + sourcePsi.getInnerExpressions().map { KotlinConverter.convertOrEmpty(it, this) } + } + + override fun asRenderString(): String = "collectionLiteral[" + valueArguments.joinToString { it.asRenderString() } + "]" + + override fun resolve(): PsiMethod? = null + + override val psi: PsiElement get() = sourcePsi + + override fun getArgumentForParameter(i: Int): UExpression? = valueArguments.getOrNull(i) + +} \ No newline at end of file diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUFunctionCallExpression.kt.181 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUFunctionCallExpression.kt.181 index b1c7001ccc5..db86b21c68b 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUFunctionCallExpression.kt.181 +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUFunctionCallExpression.kt.181 @@ -21,6 +21,7 @@ import com.intellij.psi.PsiMethod import com.intellij.psi.PsiType import org.jetbrains.kotlin.asJava.LightClassUtil import org.jetbrains.kotlin.asJava.toLightClass +import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.ConstructorDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.psi.* @@ -97,24 +98,9 @@ class KotlinUFunctionCallExpression( val resolvedCall = resolvedCall ?: return null val actualParamIndex = if (resolvedCall.extensionReceiver == null) i else i - 1 if (actualParamIndex == -1) return receiver - val (parameter, resolvedArgument) = resolvedCall.valueArguments.entries.find { it.key.index == actualParamIndex } ?: return null - val arguments = resolvedArgument.arguments - if (arguments.isEmpty()) return null - if (arguments.size == 1) { - val argument = arguments.single() - val expression = argument.getArgumentExpression() - if (parameter.varargElementType != null && argument.getSpreadElement() == null) { - return createVarargsHolder(arguments, this) - } - return KotlinConverter.convertOrEmpty(expression, this) - } - return createVarargsHolder(arguments, this) + return getArgumentExpressionByIndex(actualParamIndex, resolvedCall, this) } - private fun createVarargsHolder(arguments: List, parent: UElement?): KotlinUExpressionList = - KotlinUExpressionList(null, UastSpecialExpressionKind.VARARGS, parent).apply { - expressions = arguments.map { KotlinConverter.convertOrEmpty(it.getArgumentExpression(), parent) } - } override val typeArgumentCount: Int get() = psi.typeArguments.size @@ -171,3 +157,27 @@ class KotlinUFunctionCallExpression( } } + +internal fun getArgumentExpressionByIndex( + actualParamIndex: Int, + resolvedCall: ResolvedCall, + parent: UElement +): UExpression? { + val (parameter, resolvedArgument) = resolvedCall.valueArguments.entries.find { it.key.index == actualParamIndex } ?: return null + val arguments = resolvedArgument.arguments + if (arguments.isEmpty()) return null + if (arguments.size == 1) { + val argument = arguments.single() + val expression = argument.getArgumentExpression() + if (parameter.varargElementType != null && argument.getSpreadElement() == null) { + return createVarargsHolder(arguments, parent) + } + return KotlinConverter.convertOrEmpty(expression, parent) + } + return createVarargsHolder(arguments, parent) +} + +private fun createVarargsHolder(arguments: List, parent: UElement?): KotlinUExpressionList = + KotlinUExpressionList(null, UastSpecialExpressionKind.VARARGS, parent).apply { + expressions = arguments.map { KotlinConverter.convertOrEmpty(it.getArgumentExpression(), parent) } + } diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUObjectLiteralExpression.kt.181 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUObjectLiteralExpression.kt.181 new file mode 100644 index 00000000000..b4b70818cd3 --- /dev/null +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUObjectLiteralExpression.kt.181 @@ -0,0 +1,102 @@ +/* + * 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.openapi.diagnostic.Attachment +import com.intellij.openapi.diagnostic.Logger +import com.intellij.psi.PsiMethod +import com.intellij.psi.PsiType +import com.intellij.psi.impl.light.LightPsiClassBuilder +import org.jetbrains.kotlin.asJava.classes.KtLightClass +import org.jetbrains.kotlin.asJava.toLightClass +import org.jetbrains.kotlin.psi.KtObjectLiteralExpression +import org.jetbrains.kotlin.psi.KtSuperTypeCallEntry +import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall +import org.jetbrains.uast.* + +class KotlinUObjectLiteralExpression( + override val psi: KtObjectLiteralExpression, + givenParent: UElement? +) : KotlinAbstractUExpression(givenParent), UObjectLiteralExpression, UCallExpressionEx, KotlinUElementWithType { + + override val declaration: UClass by lz { + val lightClass: KtLightClass? = psi.objectDeclaration.toLightClass() + if (lightClass != null) { + getLanguagePlugin().convert(lightClass, this) + } + else { + logger.error( + "Failed to create light class for object declaration", + Attachment(psi.containingFile.virtualFile?.path ?: "", psi.containingFile.text)) + + getLanguagePlugin().convert(LightPsiClassBuilder(psi, ""), this) + } + } + + override fun getExpressionType() = psi.objectDeclaration.toPsiType() + + private val superClassConstructorCall by lz { + psi.objectDeclaration.superTypeListEntries.firstOrNull { it is KtSuperTypeCallEntry } as? KtSuperTypeCallEntry + } + + override val classReference: UReferenceExpression? by lz { superClassConstructorCall?.let { ObjectLiteralClassReference(it, this) } } + + override val valueArgumentCount: Int + get() = superClassConstructorCall?.valueArguments?.size ?: 0 + + override val valueArguments by lz { + val psi = superClassConstructorCall ?: return@lz emptyList() + psi.valueArguments.map { KotlinConverter.convertOrEmpty(it.getArgumentExpression(), this) } + } + + override val typeArgumentCount: Int + get() = superClassConstructorCall?.typeArguments?.size ?: 0 + + override val typeArguments by lz { + val psi = superClassConstructorCall ?: return@lz emptyList() + psi.typeArguments.map { it.typeReference.toPsiType(this, boxed = true) } + } + + override fun resolve() = superClassConstructorCall?.resolveCallToDeclaration(this) as? PsiMethod + + override fun getArgumentForParameter(i: Int): UExpression? = + superClassConstructorCall?.let { it.getResolvedCall(it.analyze()) }?.let { getArgumentExpressionByIndex(i, it, this) } + + private class ObjectLiteralClassReference( + override val psi: KtSuperTypeCallEntry, + givenParent: UElement? + ) : KotlinAbstractUElement(givenParent), USimpleNameReferenceExpression { + + override val javaPsi = null + override val sourcePsi = psi + + override fun resolve() = (psi.resolveCallToDeclaration(this) as? PsiMethod)?.containingClass + + override val annotations: List + get() = emptyList() + + override val resolvedName: String? + get() = identifier + + override val identifier: String + get() = psi.name ?: "" + } + + companion object { + val logger by lz { Logger.getInstance(KotlinUObjectLiteralExpression::class.java) } + } +} \ No newline at end of file diff --git a/plugins/uast-kotlin/testData/ParametersDisorder.kt.181 b/plugins/uast-kotlin/testData/ParametersDisorder.kt.181 index 70989d01e67..c6a067ac19a 100644 --- a/plugins/uast-kotlin/testData/ParametersDisorder.kt.181 +++ b/plugins/uast-kotlin/testData/ParametersDisorder.kt.181 @@ -25,4 +25,11 @@ class A { fun String.with2Receivers(a: Int, b: Float) {} +} + +open class Parent(a: String, b: Int) + +fun objectLiteral() { + + object : Parent(b = 1, a = "foo") } \ No newline at end of file diff --git a/plugins/uast-kotlin/testData/ParametersDisorder.log.txt.181 b/plugins/uast-kotlin/testData/ParametersDisorder.log.txt.181 index 07fc9a51a7f..dd9c96d4f8e 100644 --- a/plugins/uast-kotlin/testData/ParametersDisorder.log.txt.181 +++ b/plugins/uast-kotlin/testData/ParametersDisorder.log.txt.181 @@ -138,6 +138,13 @@ UFile (package = ) USimpleNameReferenceExpression (identifier = with2Receivers) ULiteralExpression (value = 8) ULiteralExpression (value = 7.0) + UAnnotationMethod (name = objectLiteral) + UBlockExpression + UObjectLiteralExpression + ULiteralExpression (value = 1) + ULiteralExpression (value = "foo") + UClass (name = null) + UAnnotationMethod (name = ParametersDisorderKt$objectLiteral$1) UClass (name = A) UAnnotationMethod (name = with2Receivers) UParameter (name = $receiver) @@ -148,3 +155,9 @@ UFile (package = ) UAnnotation (fqName = org.jetbrains.annotations.NotNull) UBlockExpression UAnnotationMethod (name = A) + UClass (name = Parent) + UAnnotationMethod (name = Parent) + UParameter (name = a) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UParameter (name = b) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) diff --git a/plugins/uast-kotlin/testData/ParametersDisorder.render.txt.181 b/plugins/uast-kotlin/testData/ParametersDisorder.render.txt.181 index 46112aa34ce..d0292e57874 100644 --- a/plugins/uast-kotlin/testData/ParametersDisorder.render.txt.181 +++ b/plugins/uast-kotlin/testData/ParametersDisorder.render.txt.181 @@ -19,6 +19,10 @@ public final class ParametersDisorderKt { "def".with2Receivers(8, 7.0) }) } + public static final fun objectLiteral() : void { + anonymous object : Parent(b = 1, a = "foo") + + } } public final class A { @@ -26,3 +30,7 @@ public final class A { } public fun A() = UastEmptyExpression } + +public class Parent { + public fun Parent(@org.jetbrains.annotations.NotNull a: java.lang.String, @org.jetbrains.annotations.NotNull b: int) = UastEmptyExpression +} diff --git a/plugins/uast-kotlin/tests/KotlinUastApiTest.kt.181 b/plugins/uast-kotlin/tests/KotlinUastApiTest.kt.181 index 75b0be02573..4a508dde279 100644 --- a/plugins/uast-kotlin/tests/KotlinUastApiTest.kt.181 +++ b/plugins/uast-kotlin/tests/KotlinUastApiTest.kt.181 @@ -6,7 +6,6 @@ import com.intellij.testFramework.UsefulTestCase import org.jetbrains.kotlin.asJava.toLightAnnotation import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.getParentOfType -import org.jetbrains.kotlin.psi.psiUtil.getValueParameterList import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase import org.jetbrains.kotlin.utils.addToStdlib.cast import org.jetbrains.uast.* @@ -338,6 +337,7 @@ class KotlinUastApiTest : AbstractKotlinUastTest() { ) assertArguments(listOf("\"%i %i %i\"", "\"\".chunked(2).toTypedArray()"), "format(\"%i %i %i\", *\"\".chunked(2).toTypedArray())") assertArguments(listOf("\"def\"", "8", "7.0"), "with2Receivers(8, 7.0F)") + assertArguments(listOf("\"foo\"", "1"), "object : Parent(b = 1, a = \"foo\")\n") } }