172: Revert "UAST: support for JvmDeclarationUElement"

This reverts commit db6a2390a22d4b35246cc4c6d246a5d7752f3506.
This commit is contained in:
Nikolay Krasko
2018-01-11 20:12:40 +03:00
parent 17a5ce809f
commit b02ec40a4c
18 changed files with 828 additions and 90 deletions
@@ -28,7 +28,7 @@ import org.jetbrains.uast.*
import org.jetbrains.uast.kotlin.expressions.KotlinUElvisExpression
import org.jetbrains.uast.kotlin.psi.UastKotlinPsiVariable
abstract class KotlinAbstractUElement(private val givenParent: UElement?) : UElement, JvmDeclarationUElement {
abstract class KotlinAbstractUElement(private val givenParent: UElement?) : UElement {
override val uastParent: UElement? by lz {
givenParent ?: convertParent()
@@ -175,11 +175,7 @@ private fun findAnnotationClassFromConstructorParameter(parameter: KtParameter):
}
abstract class KotlinAbstractUExpression(givenParent: UElement?)
: KotlinAbstractUElement(givenParent), UExpression, JvmDeclarationUElement {
override val javaPsi = null
override val sourcePsi
get() = psi
: KotlinAbstractUElement(givenParent), UExpression {
override val annotations: List<UAnnotation>
get() {
@@ -80,7 +80,7 @@ class KotlinUastLanguagePlugin : UastLanguagePlugin {
if (!element.isJvmElement) return null
return convertDeclarationOrElement(element, parent, requiredType)
}
override fun convertElementWithParent(element: PsiElement, requiredType: Class<out UElement>?): UElement? {
if (!element.isJvmElement) return null
if (element is PsiFile) return convertDeclaration(element, null, requiredType)
@@ -117,7 +117,7 @@ class KotlinUastLanguagePlugin : UastLanguagePlugin {
val resolvedCall = element.getResolvedCall(element.analyze()) ?: return null
val resultingDescriptor = resolvedCall.resultingDescriptor
if (resultingDescriptor !is FunctionDescriptor || resultingDescriptor.name.asString() != methodName) return null
val parent = element.parent
val parentUElement = convertElementWithParent(parent, null) ?: return null
@@ -134,7 +134,7 @@ class KotlinUastLanguagePlugin : UastLanguagePlugin {
if (element !is KtCallExpression) return null
val resolvedCall = element.getResolvedCall(element.analyze()) ?: return null
val resultingDescriptor = resolvedCall.resultingDescriptor
if (resultingDescriptor !is ConstructorDescriptor
if (resultingDescriptor !is ConstructorDescriptor
|| resultingDescriptor.returnType.constructor.declarationDescriptor?.name?.asString() != fqName) {
return null
}
@@ -151,13 +151,9 @@ class KotlinUastLanguagePlugin : UastLanguagePlugin {
internal fun convertDeclaration(element: PsiElement,
givenParent: UElement?,
requiredType: Class<out UElement>?): UElement? {
fun <P : PsiElement> build(ctor: (P, UElement?) -> UElement): () -> UElement? = { ctor(element as P, givenParent) }
fun <P : PsiElement, K : KtElement> buildKt(ktElement: K, ctor: (P, K, UElement?) -> UElement): () -> UElement? =
{ ctor(element as P, ktElement, givenParent) }
fun <P : PsiElement, K : KtElement> buildKtOpt(ktElement: K?, ctor: (P, K?, UElement?) -> UElement): () -> UElement? =
{ ctor(element as P, ktElement, givenParent) }
fun <P : PsiElement> build(ctor: (P, UElement?) -> UElement): () -> UElement? {
return { ctor(element as P, givenParent) }
}
val original = element.originalElement
return with(requiredType) {
@@ -169,11 +165,10 @@ class KotlinUastLanguagePlugin : UastLanguagePlugin {
}
else -> el<UClass> { KotlinUClass.create(original, givenParent) }
}
is KtLightFieldImpl.KtLightEnumConstant -> el<UEnumConstant>(buildKtOpt(original.kotlinOrigin, ::KotlinUEnumConstant))
is KtLightField -> el<UField>(buildKtOpt(original.kotlinOrigin, ::KotlinUField))
is KtLightParameter -> el<UParameter>(buildKtOpt(original.kotlinOrigin, ::KotlinUParameter))
is UastKotlinPsiParameter -> el<UParameter>(buildKt(original.ktParameter, ::KotlinUParameter))
is UastKotlinPsiVariable -> el<UVariable>(buildKt(original.ktElement, ::KotlinUVariable))
is KtLightFieldImpl.KtLightEnumConstant -> el<UEnumConstant>(build(::KotlinUEnumConstant))
is KtLightField -> el<UField>(build(::KotlinUField))
is KtLightParameter, is UastKotlinPsiParameter -> el<UParameter>(build(::KotlinUParameter))
is UastKotlinPsiVariable -> el<UVariable>(build(::KotlinUVariable))
is KtEnumEntry -> el<UEnumConstant> {
convertEnumEntry(original, givenParent)
@@ -220,7 +215,7 @@ class KotlinUastLanguagePlugin : UastLanguagePlugin {
val ownerFunction = original.ownerFunction as? KtFunction ?: return null
val lightMethod = LightClassUtil.getLightClassMethod(ownerFunction) ?: return null
val lightParameter = lightMethod.parameterList.parameters.find { it.name == original.name } ?: return null
KotlinUParameter(lightParameter, original, givenParent)
KotlinUParameter(lightParameter, givenParent)
}
is KtFile -> el<UFile> { KotlinUFile(original, this@KotlinUastLanguagePlugin) }
@@ -246,7 +241,7 @@ class KotlinUastLanguagePlugin : UastLanguagePlugin {
private fun convertEnumEntry(original: KtEnumEntry, givenParent: UElement?): UElement? {
return LightClassUtil.getLightClassBackingField(original)?.let { psiField ->
if (psiField is KtLightFieldImpl.KtLightEnumConstant) {
KotlinUEnumConstant(psiField, psiField.kotlinOrigin, givenParent)
KotlinUEnumConstant(psiField, givenParent)
}
else {
null
@@ -280,7 +275,7 @@ private fun convertNonLocalProperty(property: KtProperty,
val methods = LightClassUtil.getLightClassPropertyMethods(property)
return methods.backingField?.let { backingField ->
with(requiredType) {
el<UField> { KotlinUField(backingField, (backingField as? KtLightElement<*,*>)?.kotlinOrigin, givenParent) }
el<UField> { KotlinUField(backingField, givenParent) }
}
} ?: methods.getter?.let { getter ->
KotlinUastLanguagePlugin().convertDeclaration(getter, givenParent, requiredType)
@@ -310,7 +305,7 @@ internal object KotlinConverter {
val declarationsExpression = KotlinUDeclarationsExpression(givenParent)
declarationsExpression.apply {
declarations = element.parameters.mapIndexed { i, p ->
KotlinUParameter(UastKotlinPsiParameter.create(p, element, declarationsExpression, i), p, this)
KotlinUParameter(UastKotlinPsiParameter.create(p, element, declarationsExpression, i), this)
}
}
}
@@ -320,7 +315,7 @@ internal object KotlinConverter {
if (element is KtProperty && !element.isLocal) {
el<UField> {
LightClassUtil.getLightClassBackingField(element)?.let {
KotlinUField(it, element, givenParent)
KotlinUField(it, givenParent)
}
}
}
@@ -420,13 +415,13 @@ internal object KotlinConverter {
is KtDestructuringDeclaration -> expr<UDeclarationsExpression> {
val declarationsExpression = KotlinUDestructuringDeclarationExpression(givenParent, expression)
declarationsExpression.apply {
val tempAssignment = KotlinULocalVariable(UastKotlinPsiVariable.create(expression, declarationsExpression), expression, declarationsExpression)
val tempAssignment = KotlinULocalVariable(UastKotlinPsiVariable.create(expression, declarationsExpression), declarationsExpression)
val destructuringAssignments = expression.entries.mapIndexed { i, entry ->
val psiFactory = KtPsiFactory(expression.project)
val initializer = psiFactory.createAnalyzableExpression("${tempAssignment.name}.component${i + 1}()",
expression.containingFile)
initializer.destructuringDeclarationInitializer = true
KotlinULocalVariable(UastKotlinPsiVariable.create(entry, tempAssignment.psi, declarationsExpression, initializer), entry, declarationsExpression)
KotlinULocalVariable(UastKotlinPsiVariable.create(entry, tempAssignment.psi, declarationsExpression, initializer), declarationsExpression)
}
declarations = listOf(tempAssignment) + destructuringAssignments
}
@@ -551,7 +546,7 @@ private fun convertVariablesDeclaration(
val declarationsExpression = KotlinUDeclarationsExpression(null, parent, psi)
val parentPsiElement = parent?.psi
val variable = KotlinUAnnotatedLocalVariable(
UastKotlinPsiVariable.create(psi, parentPsiElement, declarationsExpression), psi, declarationsExpression) { annotationParent ->
UastKotlinPsiVariable.create(psi, parentPsiElement, declarationsExpression), declarationsExpression) { annotationParent ->
psi.annotationEntries.map { KotlinUAnnotation(it, annotationParent) }
}
return declarationsExpression.apply { declarations = listOf(variable) }
@@ -31,7 +31,7 @@ import org.jetbrains.uast.java.AbstractJavaUClass
import org.jetbrains.uast.kotlin.declarations.KotlinUMethod
import org.jetbrains.uast.kotlin.declarations.UastLightIdentifier
abstract class AbstractKotlinUClass(private val givenParent: UElement?) : AbstractJavaUClass(), JvmDeclarationUElement {
abstract class AbstractKotlinUClass(private val givenParent: UElement?) : AbstractJavaUClass() {
override val uastParent: UElement? by lz { givenParent ?: convertParent() }
//TODO: should be merged with KotlinAbstractUElement.convertParent() after detaching from AbstractJavaUClass
@@ -42,6 +42,7 @@ abstract class AbstractKotlinUClass(private val givenParent: UElement?) : Abstra
else -> it.toUElement()
}
} ?: (psi.parent ?: psi.containingFile).toUElement()
}
open class KotlinUClass private constructor(
@@ -51,10 +52,6 @@ open class KotlinUClass private constructor(
val ktClass = psi.kotlinOrigin
override val javaPsi: KtLightClass = psi
override val sourcePsi: KtClassOrObject? = ktClass
override val psi = unwrap<UClass, PsiClass>(psi)
override fun getSourceElement() = sourcePsi ?: this
@@ -119,7 +116,6 @@ open class KotlinUClass private constructor(
else -> KotlinUClass(psi, containingElement)
}
}
}
open class KotlinConstructorUMethod(
@@ -153,10 +149,6 @@ open class KotlinConstructorUMethod(
}
}
override val javaPsi = psi
override val sourcePsi = psi.kotlinOrigin
open protected fun getBodyExpressions(): List<KtExpression> {
if (isPrimary) return getInitializers()
val bodyExpression = (psi.kotlinOrigin as? KtFunction)?.bodyExpression ?: return emptyList()
@@ -186,10 +178,6 @@ class KotlinUAnonymousClass(
override val psi: PsiAnonymousClass = unwrap<UAnonymousClass, PsiAnonymousClass>(psi)
override val javaPsi: PsiAnonymousClass = psi
override val sourcePsi: KtClassOrObject? = (psi as? KtLightClass)?.kotlinOrigin
override fun getOriginalElement(): PsiElement? = super<AbstractKotlinUClass>.getOriginalElement()
override fun getSuperClass(): UClass? = super<AbstractKotlinUClass>.getSuperClass()
@@ -219,10 +207,6 @@ class KotlinScriptUClass(
override val uastAnchor: UElement
get() = UIdentifier(nameIdentifier, this)
override val javaPsi: PsiClass = psi
override val sourcePsi: KtClassOrObject? = psi.kotlinOrigin
override val psi = unwrap<UClass, KtLightClassForScript>(psi)
override fun getSuperClass(): UClass? = super.getSuperClass()
@@ -256,11 +240,8 @@ class KotlinScriptUClass(
val initializers = script.declarations.filterIsInstance<KtScriptInitializer>()
KotlinUBlockExpression.create(initializers, this)
}
override val javaPsi = psi
override val sourcePsi = psi.kotlinOrigin
}
}
private fun reportConvertFailure(psiMethod: PsiMethod): Nothing {
val isValid = psiMethod.isValid
val report = KotlinExceptionWithAttachments(
@@ -0,0 +1,56 @@
/*
* 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.PsiClass
import com.intellij.psi.PsiComment
import com.intellij.psi.PsiRecursiveElementWalkingVisitor
import org.jetbrains.kotlin.asJava.findFacadeClass
import org.jetbrains.kotlin.asJava.toLightClass
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.uast.*
import java.util.*
class KotlinUFile(override val psi: KtFile, override val languagePlugin: UastLanguagePlugin) : UFile {
override val packageName: String
get() = psi.packageFqName.asString()
override val annotations: List<UAnnotation>
get() = psi.annotationEntries.map { KotlinUAnnotation(it, this) }
override val allCommentsInFile by lz {
val comments = ArrayList<UComment>(0)
psi.accept(object : PsiRecursiveElementWalkingVisitor() {
override fun visitComment(comment: PsiComment) {
comments += UComment(comment, this@KotlinUFile)
}
})
comments
}
override val imports by lz { psi.importDirectives.map { KotlinUImportStatement(it, this) } }
override val classes by lz {
val facadeOrScriptClass = if (psi.isScript()) psi.script?.toLightClass() else psi.findFacadeClass()
val classes = psi.declarations.mapNotNull { (it as? KtClassOrObject)?.toLightClass()?.toUClass() }
(facadeOrScriptClass?.toUClass()?.let { listOf(it) } ?: emptyList()) + classes
}
private fun PsiClass.toUClass() = languagePlugin.convertOpt<UClass>(this, this@KotlinUFile)
}
@@ -0,0 +1,65 @@
/*
* 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 org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtImportDirective
import org.jetbrains.kotlin.psi.KtReferenceExpression
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedElementSelector
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UImportStatement
import org.jetbrains.uast.USimpleNameReferenceExpression
class KotlinUImportStatement(
override val psi: KtImportDirective,
givenParent: UElement?
) : KotlinAbstractUElement(givenParent), UImportStatement {
override val isOnDemand: Boolean
get() = psi.isAllUnder
private val importRef by lz {
psi.importedReference?.let {
ImportReference(it, psi.name ?: psi.text, this, psi)
}
}
override val importReference: UElement?
get() = importRef
override fun resolve() = importRef?.resolve()
private class ImportReference(
override val psi: KtExpression,
override val identifier: String,
givenParent: UElement?,
private val importDirective: KtImportDirective
) : KotlinAbstractUExpression(givenParent), USimpleNameReferenceExpression {
override val resolvedName: String?
get() = identifier
override fun asRenderString(): String = importDirective.importedFqName?.asString() ?: psi.text
override fun resolve(): PsiElement? {
val reference = psi.getQualifiedElementSelector() as? KtReferenceExpression ?: return null
val bindingContext = reference.analyze()
val referenceTarget = bindingContext[BindingContext.REFERENCE_TARGET, reference] ?: return null
return referenceTarget.toSource()?.getMaybeLightElement(this)
}
}
}
@@ -38,12 +38,6 @@ open class KotlinUMethod(
) : KotlinAbstractUElement(givenParent), UAnnotationMethod, JavaUElementWithComments, PsiMethod by psi {
override val psi: KtLightMethod = unwrap<UMethod, KtLightMethod>(psi)
override val javaPsi = psi
override val sourcePsi = psi.kotlinOrigin
override fun getSourceElement() = sourcePsi ?: this
override val uastDefaultValue by lz {
val annotationParameter = psi.kotlinOrigin as? KtParameter ?: return@lz null
val defaultValue = annotationParameter.defaultValue ?: return@lz null
@@ -63,7 +57,7 @@ open class KotlinUMethod(
}
override val uastParameters by lz {
psi.parameterList.parameters.map { KotlinUParameter(it, (it as? KtLightElement<*, *>)?.kotlinOrigin, this) }
psi.parameterList.parameters.map { KotlinUParameter(it, this) }
}
override val uastAnchor: UElement
@@ -19,7 +19,10 @@ package org.jetbrains.uast.kotlin
import com.intellij.psi.*
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.elements.KtLightElement
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.KtNamedDeclaration
import org.jetbrains.kotlin.psi.KtParameter
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.psi.KtVariableDeclaration
import org.jetbrains.uast.*
import org.jetbrains.uast.internal.acceptList
import org.jetbrains.uast.java.JavaAbstractUExpression
@@ -83,13 +86,9 @@ abstract class AbstractKotlinUVariable(givenParent: UElement?)
class KotlinUVariable(
psi: PsiVariable,
override val sourcePsi: KtElement,
givenParent: UElement?
) : AbstractKotlinUVariable(givenParent), UVariable, PsiVariable by psi {
override val javaPsi = unwrap<UVariable, PsiVariable>(psi)
override val psi = javaPsi
override val psi = unwrap<UVariable, PsiVariable>(psi)
override val annotations by lz { psi.annotations.map { JavaUAnnotation(it, this) } }
@@ -114,13 +113,10 @@ class KotlinUVariable(
open class KotlinUParameter(
psi: PsiParameter,
override val sourcePsi: KtElement?,
givenParent: UElement?
) : AbstractKotlinUVariable(givenParent), UParameter, PsiParameter by psi {
override val javaPsi = unwrap<UParameter, PsiParameter>(psi)
override val psi = javaPsi
override val psi = unwrap<UParameter, PsiParameter>(psi)
override fun getInitializer(): PsiExpression? {
return super<AbstractKotlinUVariable>.getInitializer()
@@ -141,13 +137,10 @@ open class KotlinUParameter(
open class KotlinUField(
psi: PsiField,
override val sourcePsi: KtElement?,
givenParent: UElement?
) : AbstractKotlinUVariable(givenParent), UField, PsiField by psi {
override val javaPsi = unwrap<UField, PsiField>(psi)
override val psi = javaPsi
override val psi = unwrap<UField, PsiField>(psi)
override fun getInitializer(): PsiExpression? {
return super<AbstractKotlinUVariable>.getInitializer()
@@ -180,13 +173,10 @@ open class KotlinUField(
open class KotlinULocalVariable(
psi: PsiLocalVariable,
override val sourcePsi: KtElement,
givenParent: UElement?
) : AbstractKotlinUVariable(givenParent), ULocalVariable, PsiLocalVariable by psi {
override val javaPsi = unwrap<ULocalVariable, PsiLocalVariable>(psi)
override val psi = javaPsi
override val psi = unwrap<ULocalVariable, PsiLocalVariable>(psi)
override fun getInitializer(): PsiExpression? {
return super<AbstractKotlinUVariable>.getInitializer()
@@ -215,29 +205,24 @@ open class KotlinULocalVariable(
open class KotlinUAnnotatedLocalVariable(
psi: PsiLocalVariable,
sourcePsi: KtElement,
uastParent: UElement?,
computeAnnotations: (parent: UElement) -> List<UAnnotation>
) : KotlinULocalVariable(psi, sourcePsi, uastParent) {
) : KotlinULocalVariable(psi, uastParent) {
override val annotations: List<UAnnotation> by lz { computeAnnotations(this) }
}
open class KotlinUEnumConstant(
psi: PsiEnumConstant,
override val sourcePsi: KtElement?,
givenParent: UElement?
) : AbstractKotlinUVariable(givenParent), UEnumConstant, PsiEnumConstant by psi {
override val initializingClass: UClass? by lz {
(psi.initializingClass as? KtLightClass)?.let { initializingClass ->
KotlinUClass.create(initializingClass, this)
}
}
override val javaPsi = unwrap<UEnumConstant, PsiEnumConstant>(psi)
override val psi = javaPsi
override val psi = unwrap<UEnumConstant, PsiEnumConstant>(psi)
override fun getContainingFile(): PsiFile {
return super.getContainingFile()
@@ -260,7 +245,7 @@ open class KotlinUEnumConstant(
get() = null
override val classReference: UReferenceExpression?
get() = KotlinEnumConstantClassReference(psi, sourcePsi, this)
get() = KotlinEnumConstantClassReference(psi, this)
override val typeArgumentCount: Int
get() = 0
@@ -287,12 +272,8 @@ open class KotlinUEnumConstant(
private class KotlinEnumConstantClassReference(
override val psi: PsiEnumConstant,
override val sourcePsi: KtElement?,
private val givenParent: UElement?
) : JavaAbstractUExpression(), USimpleNameReferenceExpression {
override val javaPsi: PsiElement?
get() = psi
override val uastParent: UElement? by lz {
givenParent ?: KotlinUastLanguagePlugin().convertElementWithParent(psi.parent ?: psi.containingFile, null)
}
@@ -0,0 +1,110 @@
package org.jetbrains.uast.kotlin.expressions
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiMethod
import com.intellij.psi.PsiType
import org.jetbrains.kotlin.psi.KtBinaryExpression
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.types.CommonSupertypes
import org.jetbrains.uast.*
import org.jetbrains.uast.kotlin.*
import org.jetbrains.uast.kotlin.kinds.KotlinSpecialExpressionKinds
import org.jetbrains.uast.kotlin.psi.UastKotlinPsiVariable
private fun createVariableReferenceExpression(variable: UVariable, containingElement: UElement?) =
object : USimpleNameReferenceExpression {
override val psi: PsiElement? = null
override fun resolve(): PsiElement? = variable
override val uastParent: UElement? = containingElement
override val resolvedName: String? = variable.name
override val annotations: List<UAnnotation> = emptyList()
override val identifier: String = variable.name.orAnonymous()
}
private fun createNullLiteralExpression(containingElement: UElement?) =
object : ULiteralExpression {
override val psi: PsiElement? = null
override val uastParent: UElement? = containingElement
override val value: Any? = null
override val annotations: List<UAnnotation> = emptyList()
}
private fun createNotEqWithNullExpression(variable: UVariable, containingElement: UElement?) =
object : UBinaryExpression {
override val psi: PsiElement? = null
override val uastParent: UElement? = containingElement
override val leftOperand: UExpression by lz { createVariableReferenceExpression(variable, this) }
override val rightOperand: UExpression by lz { createNullLiteralExpression(this) }
override val operator: UastBinaryOperator = UastBinaryOperator.NOT_EQUALS
override val operatorIdentifier: UIdentifier? = UIdentifier(null, this)
override fun resolveOperator(): PsiMethod? = null
override val annotations: List<UAnnotation> = emptyList()
}
private fun createElvisExpressions(
left: KtExpression,
right: KtExpression,
containingElement: UElement?,
psiParent: PsiElement): List<UExpression> {
val declaration = KotlinUDeclarationsExpression(containingElement)
val tempVariable = KotlinULocalVariable(UastKotlinPsiVariable.create(left, declaration, psiParent), declaration)
declaration.declarations = listOf(tempVariable)
val ifExpression = object : UIfExpression {
override val psi: PsiElement? = null
override val uastParent: UElement? = containingElement
override val condition: UExpression by lz { createNotEqWithNullExpression(tempVariable, this) }
override val thenExpression: UExpression? by lz { createVariableReferenceExpression(tempVariable, this) }
override val elseExpression: UExpression? by lz { KotlinConverter.convertExpression(right, this ) }
override val isTernary: Boolean = false
override val annotations: List<UAnnotation> = emptyList()
override val ifIdentifier: UIdentifier = UIdentifier(null, this)
override val elseIdentifier: UIdentifier? = UIdentifier(null, this)
}
return listOf(declaration, ifExpression)
}
fun createElvisExpression(elvisExpression: KtBinaryExpression, givenParent: UElement?): UExpression {
val left = elvisExpression.left ?: return UastEmptyExpression
val right = elvisExpression.right ?: return UastEmptyExpression
return KotlinUElvisExpression(elvisExpression, left, right, givenParent)
}
class KotlinUElvisExpression(
private val elvisExpression: KtBinaryExpression,
private val left: KtExpression,
private val right: KtExpression,
givenParent: UElement?
) : KotlinAbstractUElement(givenParent), UExpressionList, KotlinEvaluatableUElement {
override val psi: PsiElement? = elvisExpression
override val kind = KotlinSpecialExpressionKinds.ELVIS
override val annotations: List<UAnnotation> = emptyList()
override val expressions: List<UExpression> by lz {
createElvisExpressions(left, right, this, elvisExpression.parent)
}
val lhsDeclaration get() = (expressions[0] as UDeclarationsExpression).declarations.single()
val rhsIfExpression get() = expressions[1] as UIfExpression
override fun asRenderString(): String {
return kind.name + " " +
expressions.joinToString(separator = "\n", prefix = "{\n", postfix = "\n}") {
it.asRenderString().withMargin
}
}
override fun getExpressionType(): PsiType? {
val leftType = left.analyze()[BindingContext.EXPRESSION_TYPE_INFO, left]?.type ?: return null
val rightType = right.analyze()[BindingContext.EXPRESSION_TYPE_INFO, right]?.type ?: return null
return CommonSupertypes
.commonSupertype(listOf(leftType, rightType))
.toPsiType(this, elvisExpression, boxed = false)
}
}
@@ -0,0 +1,59 @@
/*
* 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 org.jetbrains.kotlin.psi.KtAnonymousInitializer
import org.jetbrains.kotlin.psi.KtBlockExpression
import org.jetbrains.uast.*
class KotlinUBlockExpression(
override val psi: KtBlockExpression,
givenParent: UElement?
) : KotlinAbstractUExpression(givenParent), UBlockExpression, KotlinUElementWithType {
override val expressions by lz { psi.statements.map { KotlinConverter.convertOrEmpty(it, this) } }
class KotlinLazyUBlockExpression(
override val uastParent: UElement?,
expressionProducer: (expressionParent: UElement) -> List<UExpression>
) : UBlockExpression {
override val psi: PsiElement? = null
override val annotations: List<UAnnotation> = emptyList()
override val expressions by lz { expressionProducer(this) }
}
companion object {
fun create(initializers: List<KtAnonymousInitializer>, uastParent: UElement): UBlockExpression {
val languagePlugin = uastParent.getLanguagePlugin()
return KotlinLazyUBlockExpression(uastParent) { expressionParent ->
initializers.map { languagePlugin.convertOpt<UExpression>(it.body, expressionParent) ?: UastEmptyExpression }
}
}
}
override fun convertParent(): UElement? {
val directParent = super.convertParent()
if (directParent is UnknownKotlinExpression && directParent.psi is KtAnonymousInitializer) {
val containingUClass = directParent.getContainingUClass() ?: return directParent
containingUClass.methods
.find { it is KotlinConstructorUMethod && it.isPrimary || it is KotlinSecondaryConstructorWithInitializersUMethod }?.let {
return it.uastBody
}
}
return directParent
}
}
@@ -0,0 +1,42 @@
/*
* 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.KtCatchClause
import org.jetbrains.uast.UCatchClause
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UParameter
import org.jetbrains.uast.UTypeReferenceExpression
import org.jetbrains.uast.kotlin.psi.UastKotlinPsiParameter
class KotlinUCatchClause(
override val psi: KtCatchClause,
givenParent: UElement?
) : KotlinAbstractUElement(givenParent), UCatchClause {
override val body by lz { KotlinConverter.convertOrEmpty(psi.catchBody, this) }
override val parameters by lz {
val parameter = psi.catchParameter ?: return@lz emptyList<UParameter>()
listOf(KotlinUParameter(UastKotlinPsiParameter.create(parameter, psi, this, 0), this))
}
override val typeReferences by lz {
val parameter = psi.catchParameter ?: return@lz emptyList<UTypeReferenceExpression>()
val typeReference = parameter.typeReference ?: return@lz emptyList<UTypeReferenceExpression>()
listOf(LazyKotlinUTypeReferenceExpression(typeReference, this) { typeReference.toPsiType(this, boxed = true) } )
}
}
@@ -25,9 +25,6 @@ open class KotlinUDeclarationsExpression(
val psiAnchor: PsiElement? = null
) : KotlinAbstractUExpression(givenParent), UDeclarationsExpression {
override val sourcePsi: PsiElement?
get() = psiAnchor
override val uastParent: UElement?
get() = if (psiAnchor != null) doConvertParent(this, psiAnchor.parent) else super.uastParent
@@ -0,0 +1,42 @@
/*
* 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.idea.KotlinLanguage
import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UForEachExpression
import org.jetbrains.uast.UIdentifier
import org.jetbrains.uast.kotlin.psi.UastKotlinPsiParameter
import org.jetbrains.uast.psi.UastPsiParameterNotResolved
class KotlinUForEachExpression(
override val psi: KtForExpression,
givenParent: UElement?
) : KotlinAbstractUExpression(givenParent), UForEachExpression {
override val iteratedValue by lz { KotlinConverter.convertOrEmpty(psi.loopRange, this) }
override val body by lz { KotlinConverter.convertOrEmpty(psi.body, this) }
override val variable by lz {
val parameter = psi.loopParameter?.let { UastKotlinPsiParameter.create(it, psi, this, 0) }
?: UastPsiParameterNotResolved(psi, KotlinLanguage.INSTANCE)
KotlinUParameter(parameter, this)
}
override val forIdentifier: UIdentifier
get() = UIdentifier(null, this)
}
@@ -0,0 +1,52 @@
/*
* 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.PsiType
import org.jetbrains.kotlin.psi.KtLambdaExpression
import org.jetbrains.uast.UBlockExpression
import org.jetbrains.uast.UElement
import org.jetbrains.uast.ULambdaExpression
import org.jetbrains.uast.kotlin.psi.UastKotlinPsiParameter
import org.jetbrains.uast.withMargin
class KotlinULambdaExpression(
override val psi: KtLambdaExpression,
givenParent: UElement?
) : KotlinAbstractUExpression(givenParent), ULambdaExpression, KotlinUElementWithType {
override val functionalInterfaceType: PsiType?
get() = getFunctionalInterfaceType()
override val body by lz { KotlinConverter.convertOrEmpty(psi.bodyExpression, this) }
override val valueParameters by lz {
psi.valueParameters.mapIndexed { i, p ->
KotlinUParameter(UastKotlinPsiParameter.create(p, psi, this, i), this)
}
}
override fun asRenderString(): String {
val renderedValueParameters = if (valueParameters.isEmpty())
""
else
valueParameters.joinToString { it.asRenderString() } + " ->\n"
val expressions = (body as? UBlockExpression)?.expressions
?.joinToString("\n") { it.asRenderString().withMargin } ?: body.asRenderString()
return "{ $renderedValueParameters\n$expressions\n}"
}
}
@@ -0,0 +1,96 @@
/*
* Copyright 2010-2017 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.psi.ValueArgument
import org.jetbrains.uast.*
class KotlinUNamedExpression private constructor(
override val name: String?,
givenParent: UElement?,
expressionProducer: (UElement) -> UExpression
) : KotlinAbstractUElement(givenParent), UNamedExpression {
override val expression: UExpression by lz { expressionProducer(this) }
override val annotations: List<UAnnotation> = emptyList()
override val psi: PsiElement? = null
companion object {
internal fun create(name: String?, valueArgument: ValueArgument, uastParent: UElement?): UNamedExpression {
val expression = valueArgument.getArgumentExpression()
return KotlinUNamedExpression(name, uastParent) { expressionParent ->
expression?.let { expressionParent.getLanguagePlugin().convert<UExpression>(it, expressionParent) } ?: UastEmptyExpression
}
}
internal fun create(
name: String?,
valueArguments: List<ValueArgument>,
uastParent: UElement?): UNamedExpression {
return KotlinUNamedExpression(name, uastParent) { expressionParent ->
KotlinUVarargExpression(valueArguments, expressionParent)
}
}
}
}
class KotlinUVarargExpression(private val valueArgs: List<ValueArgument>,
uastParent: UElement?) : KotlinAbstractUExpression(uastParent), UCallExpression {
override val kind: UastCallKind = UastCallKind.NESTED_ARRAY_INITIALIZER
override val valueArguments: List<UExpression> by lz {
valueArgs.map {
it.getArgumentExpression()?.let { argumentExpression ->
getLanguagePlugin().convert<UExpression>(argumentExpression, this)
} ?: UastEmptyExpression
}
}
override val valueArgumentCount: Int
get() = valueArgs.size
override val psi: PsiElement?
get() = null
override val methodIdentifier: UIdentifier?
get() = null
override val classReference: UReferenceExpression?
get() = null
override val methodName: String?
get() = null
override val typeArgumentCount: Int
get() = 0
override val typeArguments: List<PsiType>
get() = emptyList()
override val returnType: PsiType?
get() = null
override fun resolve() = null
override val receiver: UExpression?
get() = null
override val receiverType: PsiType?
get() = null
}
@@ -0,0 +1,93 @@
/*
* 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.uast.*
class KotlinUObjectLiteralExpression(
override val psi: KtObjectLiteralExpression,
givenParent: UElement?
) : KotlinAbstractUExpression(givenParent), UObjectLiteralExpression, KotlinUElementWithType {
override val declaration: UClass by lz {
val lightClass: KtLightClass? = psi.objectDeclaration.toLightClass()
if (lightClass != null) {
getLanguagePlugin().convert<UClass>(lightClass, this)
}
else {
logger.error(
"Failed to create light class for object declaration",
Attachment(psi.containingFile.virtualFile?.path ?: "<no path>", psi.containingFile.text))
getLanguagePlugin().convert(LightPsiClassBuilder(psi, "<unnamed>"), 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<UExpression>()
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<PsiType>()
psi.typeArguments.map { it.typeReference.toPsiType(this, boxed = true) }
}
override fun resolve() = superClassConstructorCall?.resolveCallToDeclaration(this) as? PsiMethod
private class ObjectLiteralClassReference(
override val psi: KtSuperTypeCallEntry,
givenParent: UElement?
) : KotlinAbstractUElement(givenParent), USimpleNameReferenceExpression {
override fun resolve() = (psi.resolveCallToDeclaration(this) as? PsiMethod)?.containingClass
override val annotations: List<UAnnotation>
get() = emptyList()
override val resolvedName: String?
get() = identifier
override val identifier: String
get() = psi.name ?: "<error>"
}
companion object {
val logger by lz { Logger.getInstance(KotlinUObjectLiteralExpression::class.java) }
}
}
@@ -0,0 +1,91 @@
/*
* 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 org.jetbrains.kotlin.psi.KtBlockExpression
import org.jetbrains.kotlin.psi.KtWhenEntry
import org.jetbrains.kotlin.psi.KtWhenExpression
import org.jetbrains.uast.*
import org.jetbrains.uast.kotlin.kinds.KotlinSpecialExpressionKinds
class KotlinUSwitchExpression(
override val psi: KtWhenExpression,
givenParent: UElement?
) : KotlinAbstractUExpression(givenParent), USwitchExpression, KotlinUElementWithType {
override val expression by lz { KotlinConverter.convertOrNull(psi.subjectExpression, this) }
override val body: UExpressionList by lz {
object : KotlinUExpressionList(psi, KotlinSpecialExpressionKinds.WHEN, this@KotlinUSwitchExpression) {
override fun asRenderString() = expressions.joinToString("\n") { it.asRenderString().withMargin }
}.apply {
expressions = this@KotlinUSwitchExpression.psi.entries.map { KotlinUSwitchEntry(it, this) }
}
}
override fun asRenderString() = buildString {
val expr = expression?.let { "(" + it.asRenderString() + ") " } ?: ""
appendln("switch $expr {")
appendln(body.asRenderString())
appendln("}")
}
override val switchIdentifier: UIdentifier
get() = UIdentifier(null, this)
}
class KotlinUSwitchEntry(
override val psi: KtWhenEntry,
givenParent: UElement?
) : KotlinAbstractUExpression(givenParent), USwitchClauseExpressionWithBody {
override val caseValues by lz {
psi.conditions.map { KotlinConverter.convertWhenCondition(it, this) ?: UastEmptyExpression }
}
override val body: UExpressionList by lz {
object : KotlinUExpressionList(psi, KotlinSpecialExpressionKinds.WHEN_ENTRY, this@KotlinUSwitchEntry) {
override fun asRenderString() = buildString {
appendln("{")
expressions.forEach { appendln(it.asRenderString().withMargin) }
appendln("}")
}
}.apply {
val exprPsi = this@KotlinUSwitchEntry.psi.expression
val userExpressions = when (exprPsi) {
is KtBlockExpression -> exprPsi.statements.map { KotlinConverter.convertOrEmpty(it, this) }
else -> listOf(KotlinConverter.convertOrEmpty(exprPsi, this))
}
expressions = userExpressions + object : UBreakExpression {
override val psi: PsiElement?
get() = null
override val label: String?
get() = null
override val uastParent: UElement?
get() = this@KotlinUSwitchEntry
override val annotations: List<UAnnotation>
get() = emptyList()
}
}
}
override fun convertParent(): UElement? {
val result = KotlinConverter.unwrapElements(psi.parent)?.let { parentUnwrapped ->
KotlinUastLanguagePlugin().convertElementWithParent(parentUnwrapped, null)
}
return (result as? KotlinUSwitchExpression)?.body ?: result
}
}
@@ -0,0 +1,59 @@
package org.jetbrains.uast.kotlin.expressions
import com.intellij.psi.PsiType
import com.intellij.psi.PsiVariable
import org.jetbrains.kotlin.psi.KtFunction
import org.jetbrains.uast.*
import org.jetbrains.uast.kotlin.*
import org.jetbrains.uast.kotlin.psi.UastKotlinPsiParameter
import org.jetbrains.uast.kotlin.psi.UastKotlinPsiVariable
internal class KotlinLocalFunctionUVariable(
val function: KtFunction,
override val psi: PsiVariable,
givenParent: UElement?
) : KotlinAbstractUElement(givenParent), UVariable, PsiVariable by psi {
override val uastInitializer: UExpression? by lz {
createLocalFunctionLambdaExpression(function, this)
}
override val typeReference: UTypeReferenceExpression? = null
override val uastAnchor: UElement? = null
override val annotations: List<UAnnotation> = emptyList()
}
private class KotlinLocalFunctionULambdaExpression(
override val psi: KtFunction,
givenParent: UElement?
): KotlinAbstractUExpression(givenParent), ULambdaExpression {
override val functionalInterfaceType: PsiType? = null
override val body by lz { KotlinConverter.convertOrEmpty(psi.bodyExpression, this) }
override val valueParameters by lz {
psi.valueParameters.mapIndexed { i, p ->
KotlinUParameter(UastKotlinPsiParameter.create(p, psi, this, i), this)
}
}
override fun asRenderString(): String {
val renderedValueParameters = valueParameters.joinToString(prefix = "(", postfix = ")",
transform = KotlinUParameter::asRenderString)
val expressions = (body as? UBlockExpression)?.expressions?.joinToString("\n") {
it.asRenderString().withMargin
} ?: body.asRenderString()
return "fun $renderedValueParameters {\n${expressions.withMargin}\n}"
}
}
fun createLocalFunctionDeclaration(function: KtFunction, parent: UElement?): UDeclarationsExpression {
return KotlinUDeclarationsExpression(null, parent, function).apply {
val functionVariable = UastKotlinPsiVariable.create(function.name.orAnonymous(), function, this)
declarations = listOf(KotlinLocalFunctionUVariable(function, functionVariable, this))
}
}
fun createLocalFunctionLambdaExpression(function: KtFunction, parent: UElement?): ULambdaExpression =
KotlinLocalFunctionULambdaExpression(function, parent)
@@ -0,0 +1,29 @@
/*
* Copyright 2010-2017 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.internal
import com.intellij.psi.PsiComment
import org.jetbrains.uast.UComment
import org.jetbrains.uast.UElement
interface KotlinUElementWithComments : UElement {
override val comments: List<UComment>
get() {
val psi = psi ?: return emptyList()
return psi.children.filter { it is PsiComment }.map { UComment(it, this) }
}
}