FIR/UAST: split KotlinUIdentifier into a separate file

This commit is contained in:
Jinseong Jeon
2021-05-21 10:54:27 -07:00
committed by Ilya Kirillov
parent 68766024b3
commit 80b94a43b0
2 changed files with 64 additions and 54 deletions
@@ -0,0 +1,63 @@
/*
* 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.openapi.application.ApplicationManager
import com.intellij.psi.PsiElement
import com.intellij.psi.impl.source.tree.LeafPsiElement
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UIdentifier
import org.jetbrains.uast.toUElement
class KotlinUIdentifier constructor(
javaPsiSupplier: () -> PsiElement?,
override val sourcePsi: PsiElement?,
givenParent: UElement?
) : UIdentifier(sourcePsi, givenParent) {
override val javaPsi: PsiElement? by lazy(javaPsiSupplier) // don't know any real need to call it in production
override val psi: PsiElement?
get() = javaPsi ?: sourcePsi
init {
if (ApplicationManager.getApplication().isUnitTestMode && !acceptableSourcePsi(sourcePsi))
throw KotlinExceptionWithAttachments(
"sourcePsi should be physical leaf element but got $sourcePsi of (${sourcePsi?.javaClass})"
).withAttachment("sourcePsi.text", sourcePsi?.text)
}
private fun acceptableSourcePsi(sourcePsi: PsiElement?): Boolean {
if (sourcePsi == null) return true
if (sourcePsi is LeafPsiElement) return true
if (sourcePsi is KtElement && sourcePsi.firstChild == null) return true
// string literals could be identifiers of calls e.g. `"main" {}` in gradle.kts
if (sourcePsi is KtStringTemplateExpression && sourcePsi.parent is KtCallExpression) return true
return false
}
override val uastParent: UElement? by lazy {
if (givenParent != null) return@lazy givenParent
val parent = sourcePsi?.parent ?: return@lazy null
getIdentifierParentForCall(parent) ?: parent.toUElement()
}
private fun getIdentifierParentForCall(parent: PsiElement): UElement? {
val parentParent = parent.parent
if (parentParent is KtCallElement && parentParent.calleeExpression == parent) { // method identifiers in calls
return parentParent.toUElement()
}
(generateSequence(parent) { it.parent }.take(3).find { it is KtTypeReference && it.parent is KtConstructorCalleeExpression })?.let {
return it.parent.parent.toUElement()
}
return null
}
constructor(javaPsi: PsiElement?, sourcePsi: PsiElement?, uastParent: UElement?) : this({ javaPsi }, sourcePsi, uastParent)
constructor(sourcePsi: PsiElement?, uastParent: UElement?) : this({ null }, sourcePsi, uastParent)
}
@@ -5,17 +5,10 @@
package org.jetbrains.uast.kotlin
import com.intellij.openapi.application.ApplicationManager
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import com.intellij.psi.PsiNameIdentifierOwner
import com.intellij.psi.impl.source.tree.LeafPsiElement
import org.jetbrains.kotlin.asJava.elements.KtLightIdentifier
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UIdentifier
import org.jetbrains.uast.toUElement
import org.jetbrains.kotlin.psi.KtDeclaration
class UastLightIdentifier(
lightOwner: PsiNameIdentifierOwner,
@@ -25,49 +18,3 @@ class UastLightIdentifier(
return unwrapFakeFileForLightClass(super.getContainingFile())
}
}
class KotlinUIdentifier constructor(
javaPsiSupplier: () -> PsiElement?,
override val sourcePsi: PsiElement?,
givenParent: UElement?
) : UIdentifier(sourcePsi, givenParent) {
override val javaPsi: PsiElement? by lazy(javaPsiSupplier) // don't know any real need to call it in production
override val psi: PsiElement?
get() = javaPsi ?: sourcePsi
init {
if (ApplicationManager.getApplication().isUnitTestMode && !acceptableSourcePsi(sourcePsi))
throw KotlinExceptionWithAttachments("sourcePsi should be physical leaf element but got $sourcePsi of (${sourcePsi?.javaClass})")
.withAttachment("sourcePsi.text", sourcePsi?.text)
}
private fun acceptableSourcePsi(sourcePsi: PsiElement?): Boolean {
if (sourcePsi == null) return true
if (sourcePsi is LeafPsiElement) return true
if (sourcePsi is KtElement && sourcePsi.firstChild == null) return true
if (sourcePsi is KtStringTemplateExpression && sourcePsi.parent is KtCallExpression) return true // string literals could be identifiers of calls e.g. `"main" {}` in gradle.kts
return false
}
override val uastParent: UElement? by lazy {
if (givenParent != null) return@lazy givenParent
val parent = sourcePsi?.parent ?: return@lazy null
getIdentifierParentForCall(parent) ?: parent.toUElement()
}
private fun getIdentifierParentForCall(parent: PsiElement): UElement? {
val parentParent = parent.parent
if (parentParent is KtCallElement && parentParent.calleeExpression == parent) { // method identifiers in calls
return parentParent.toUElement()
}
(generateSequence(parent) { it.parent }.take(3).find { it is KtTypeReference && it.parent is KtConstructorCalleeExpression })?.let {
return it.parent.parent.toUElement()
}
return null
}
constructor(javaPsi: PsiElement?, sourcePsi: PsiElement?, uastParent: UElement?) : this({ javaPsi }, sourcePsi, uastParent)
constructor(sourcePsi: PsiElement?, uastParent: UElement?) : this({ null }, sourcePsi, uastParent)
}