FIR/UAST: commonize literal expressions
This commit is contained in:
committed by
Ilya Kirillov
parent
6b5bddeed7
commit
16b3d2110e
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.uast.kotlin
|
||||
|
||||
import org.jetbrains.kotlin.psi.KtEscapeStringTemplateEntry
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.psi.KtStringTemplateEntry
|
||||
import org.jetbrains.kotlin.psi.KtStringTemplateEntryWithExpression
|
||||
import org.jetbrains.uast.*
|
||||
|
||||
interface BaseKotlinConverter {
|
||||
|
||||
fun convertExpression(
|
||||
expression: KtExpression,
|
||||
givenParent: UElement?,
|
||||
requiredTypes: Array<out Class<out UElement>>
|
||||
): UExpression?
|
||||
|
||||
fun convertEntry(
|
||||
entry: KtStringTemplateEntry,
|
||||
givenParent: UElement?,
|
||||
requiredTypes: Array<out Class<out UElement>>
|
||||
): UExpression? {
|
||||
return with(requiredTypes) {
|
||||
if (entry is KtStringTemplateEntryWithExpression) {
|
||||
expr<UExpression> {
|
||||
convertOrEmpty(entry.expression, givenParent)
|
||||
}
|
||||
} else {
|
||||
expr<ULiteralExpression> {
|
||||
if (entry is KtEscapeStringTemplateEntry)
|
||||
KotlinStringULiteralExpression(entry, givenParent, entry.unescapedValue)
|
||||
else
|
||||
KotlinStringULiteralExpression(entry, givenParent)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun convertOrEmpty(expression: KtExpression?, parent: UElement?): UExpression {
|
||||
return expression?.let { convertExpression(it, parent, DEFAULT_EXPRESSION_TYPES_LIST) } ?: UastEmptyExpression(parent)
|
||||
}
|
||||
|
||||
fun convertOrNull(expression: KtExpression?, parent: UElement?): UExpression? {
|
||||
return if (expression != null) convertExpression(expression, parent, DEFAULT_EXPRESSION_TYPES_LIST) else null
|
||||
}
|
||||
}
|
||||
+2
@@ -14,6 +14,8 @@ import org.jetbrains.uast.UExpression
|
||||
interface BaseKotlinUastResolveProviderService {
|
||||
fun isJvmElement(psiElement: PsiElement): Boolean
|
||||
|
||||
val baseKotlinConverter: BaseKotlinConverter
|
||||
|
||||
fun convertParent(uElement: UElement): UElement?
|
||||
|
||||
fun resolveToDeclaration(ktExpression: KtExpression): PsiElement?
|
||||
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.uast.kotlin
|
||||
|
||||
import com.intellij.psi.PsiLanguageInjectionHost
|
||||
import org.jetbrains.kotlin.psi.KtStringTemplateExpression
|
||||
import org.jetbrains.uast.*
|
||||
import org.jetbrains.uast.expressions.UInjectionHost
|
||||
|
||||
class KotlinStringTemplateUPolyadicExpression(
|
||||
override val sourcePsi: KtStringTemplateExpression,
|
||||
givenParent: UElement?
|
||||
) : KotlinAbstractUExpression(givenParent),
|
||||
UPolyadicExpression,
|
||||
KotlinUElementWithType,
|
||||
KotlinEvaluatableUElement,
|
||||
UInjectionHost {
|
||||
override val operands: List<UExpression> by lz {
|
||||
sourcePsi.entries.map {
|
||||
baseResolveProviderService.baseKotlinConverter.convertEntry(
|
||||
it,
|
||||
this,
|
||||
DEFAULT_EXPRESSION_TYPES_LIST
|
||||
)!!
|
||||
}.takeIf { it.isNotEmpty() } ?: listOf(KotlinStringULiteralExpression(sourcePsi, this, ""))
|
||||
}
|
||||
override val operator = UastBinaryOperator.PLUS
|
||||
|
||||
override val psiLanguageInjectionHost: PsiLanguageInjectionHost get() = sourcePsi
|
||||
override val isString: Boolean get() = true
|
||||
|
||||
override fun asRenderString(): String = if (operands.isEmpty()) "\"\"" else super<UPolyadicExpression>.asRenderString()
|
||||
override fun asLogString(): String = if (operands.isEmpty()) "UPolyadicExpression (value = \"\")" else super.asLogString()
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.uast.kotlin
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiType
|
||||
import org.jetbrains.kotlin.psi.KtEscapeStringTemplateEntry
|
||||
import org.jetbrains.uast.UElement
|
||||
import org.jetbrains.uast.ULiteralExpression
|
||||
import org.jetbrains.uast.kotlin.internal.KotlinFakeUElement
|
||||
import org.jetbrains.uast.wrapULiteral
|
||||
|
||||
class KotlinStringULiteralExpression(
|
||||
override val sourcePsi: PsiElement,
|
||||
givenParent: UElement?,
|
||||
val text: String
|
||||
) : KotlinAbstractUExpression(givenParent), ULiteralExpression, KotlinUElementWithType, KotlinFakeUElement {
|
||||
constructor(psi: PsiElement, uastParent: UElement?)
|
||||
: this(psi, uastParent, if (psi is KtEscapeStringTemplateEntry) psi.unescapedValue else psi.text)
|
||||
|
||||
override val value: String
|
||||
get() = text
|
||||
|
||||
override fun evaluate() = value
|
||||
|
||||
override fun getExpressionType(): PsiType = PsiType.getJavaLangString(sourcePsi.manager, sourcePsi.resolveScope)
|
||||
|
||||
override fun unwrapToSourcePsi(): List<PsiElement> = listOfNotNull(wrapULiteral(this).sourcePsi)
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.uast.kotlin
|
||||
|
||||
import com.intellij.psi.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.internal.DelegatedMultiResolve
|
||||
|
||||
class KotlinUCollectionLiteralExpression(
|
||||
override val sourcePsi: KtCollectionLiteralExpression,
|
||||
givenParent: UElement?
|
||||
) : KotlinAbstractUExpression(givenParent), UCallExpressionEx, DelegatedMultiResolve, 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<PsiType> get() = listOfNotNull((returnType as? PsiArrayType)?.componentType)
|
||||
|
||||
override val valueArgumentCount: Int
|
||||
get() = sourcePsi.getInnerExpressions().size
|
||||
|
||||
override val valueArguments by lazy {
|
||||
sourcePsi.getInnerExpressions().map {
|
||||
baseResolveProviderService.baseKotlinConverter.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)
|
||||
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.uast.kotlin
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.KtNodeTypes
|
||||
import org.jetbrains.kotlin.psi.KtConstantExpression
|
||||
import org.jetbrains.uast.UElement
|
||||
import org.jetbrains.uast.ULiteralExpression
|
||||
import org.jetbrains.uast.kotlin.internal.KotlinFakeUElement
|
||||
import org.jetbrains.uast.wrapULiteral
|
||||
|
||||
class KotlinULiteralExpression(
|
||||
override val sourcePsi: KtConstantExpression,
|
||||
givenParent: UElement?
|
||||
) : KotlinAbstractUExpression(givenParent), ULiteralExpression, KotlinUElementWithType, KotlinEvaluatableUElement, KotlinFakeUElement {
|
||||
override val isNull: Boolean
|
||||
get() = sourcePsi.unwrapBlockOrParenthesis().node?.elementType == KtNodeTypes.NULL
|
||||
|
||||
override val value by lz { evaluate() }
|
||||
|
||||
override fun unwrapToSourcePsi(): List<PsiElement> = listOfNotNull(wrapULiteral(this).sourcePsi)
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.uast.kotlin.internal
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
|
||||
interface KotlinFakeUElement {
|
||||
fun unwrapToSourcePsi(): List<PsiElement>
|
||||
}
|
||||
+12
@@ -10,7 +10,10 @@ import com.intellij.psi.PsiFile
|
||||
import org.jetbrains.kotlin.asJava.elements.FakeFileForLightClass
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightElement
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightMember
|
||||
import org.jetbrains.kotlin.psi.KtBlockExpression
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.psi.KtPsiUtil
|
||||
import org.jetbrains.uast.UDeclaration
|
||||
import org.jetbrains.uast.UElement
|
||||
import java.util.function.Supplier
|
||||
@@ -33,3 +36,12 @@ fun getKotlinMemberOrigin(element: PsiElement?): KtDeclaration? {
|
||||
(element as? KtLightElement<*, *>)?.kotlinOrigin?.let { return it as? KtDeclaration }
|
||||
return null
|
||||
}
|
||||
|
||||
fun KtExpression.unwrapBlockOrParenthesis(): KtExpression {
|
||||
val innerExpression = KtPsiUtil.safeDeparenthesize(this)
|
||||
if (innerExpression is KtBlockExpression) {
|
||||
val statement = innerExpression.statements.singleOrNull() ?: return this
|
||||
return KtPsiUtil.safeDeparenthesize(statement)
|
||||
}
|
||||
return innerExpression
|
||||
}
|
||||
|
||||
@@ -5,11 +5,13 @@
|
||||
|
||||
package org.jetbrains.uast.kotlin
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.uast.DEFAULT_EXPRESSION_TYPES_LIST
|
||||
import org.jetbrains.uast.DEFAULT_TYPES_LIST
|
||||
import org.jetbrains.uast.UElement
|
||||
import org.jetbrains.uast.UExpression
|
||||
import org.jetbrains.uast.kotlin.internal.KotlinFakeUElement
|
||||
|
||||
fun expressionTypes(requiredType: Class<out UElement>?) =
|
||||
requiredType?.let { arrayOf(it) } ?: DEFAULT_EXPRESSION_TYPES_LIST
|
||||
@@ -47,3 +49,8 @@ val identifiersTokens = setOf(
|
||||
KtTokens.THIS_KEYWORD, KtTokens.SUPER_KEYWORD,
|
||||
KtTokens.GET_KEYWORD, KtTokens.SET_KEYWORD
|
||||
)
|
||||
|
||||
fun UElement.toSourcePsiFakeAware(): List<PsiElement> {
|
||||
if (this is KotlinFakeUElement) return this.unwrapToSourcePsi()
|
||||
return listOfNotNull(this.sourcePsi)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user