Light classes in IDE: Make light class delegate construction a two step process

Step 0: Light class object is created, no delegates are computed
Step 1: constructs dummy delegate which can not be relied upon to know signature of any member
		It can be used to construct light field and light method objects
		(which can correctly respond to some queries) before constructing real delegate
Step 2:
		Construct real delegate if dummy delegate is not enough to respond to a query

This speeds up multiple scenarios where getMethods() and getFields() are called on numerous classes

Dummy delegate's faster consruction is achieved by using specially setup dumb analysis instead of ide analysis

Introduce LazyLightClassDataHolder: which manages creation of Step 1 and Step 2 delegates
Introduce MemberIndex: keeping track of member creation order, helps matching light class delegates created in different contexts
KtLightMethod and Field: make use of dummy delegate
KtLightMethod no longer extends LightMethod since it requires eager delegate construction
KtLightMethod now implements PsiAnnotationMethod for convenience (ClsMethodImpl implements PsiAnnotationMethod)
This commit is contained in:
Pavel V. Talanov
2017-02-16 16:26:11 +03:00
parent ed9e94c632
commit daef8a0eed
15 changed files with 683 additions and 200 deletions
@@ -20,7 +20,10 @@ import com.intellij.psi.PsiCodeBlock
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiMethod
import com.intellij.psi.PsiNameIdentifierOwner
import org.jetbrains.kotlin.asJava.elements.*
import org.jetbrains.kotlin.asJava.elements.KtLightElement
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.asJava.elements.isGetter
import org.jetbrains.kotlin.asJava.elements.isSetter
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.uast.*
@@ -30,9 +33,15 @@ import org.jetbrains.uast.kotlin.*
open class KotlinUMethod(
psi: KtLightMethod,
override val uastParent: UElement?
) : UMethod, JavaUElementWithComments, PsiMethod by psi {
) : UAnnotationMethod, JavaUElementWithComments, PsiMethod by psi {
override val psi: KtLightMethod = unwrap<UMethod, KtLightMethod>(psi)
override val uastDefaultValue by lz {
val annotationParameter = psi.kotlinOrigin as? KtParameter ?: return@lz null
val defaultValue = annotationParameter.defaultValue ?: return@lz null
getLanguagePlugin().convertElement(defaultValue, this) as? UExpression
}
private val kotlinOrigin = (psi.originalElement as KtLightElement<*, *>).kotlinOrigin
override val annotations by lz {
@@ -73,20 +82,6 @@ open class KotlinUMethod(
override fun hashCode() = psi.hashCode()
companion object {
fun create(psi: KtLightMethod, containingElement: UElement?) = when (psi) {
is KtLightMethodImpl.KtLightAnnotationMethod -> KotlinUAnnotationMethod(psi, containingElement)
else -> KotlinUMethod(psi, containingElement)
}
}
}
class KotlinUAnnotationMethod(
override val psi: KtLightMethodImpl.KtLightAnnotationMethod,
containingElement: UElement?
) : KotlinUMethod(psi, containingElement), UAnnotationMethod {
override val uastDefaultValue by lz {
val annotationParameter = psi.kotlinOrigin as? KtParameter ?: return@lz null
val defaultValue = annotationParameter.defaultValue ?: return@lz null
getLanguagePlugin().convertElement(defaultValue, this) as? UExpression
fun create(psi: KtLightMethod, containingElement: UElement?) = KotlinUMethod(psi, containingElement)
}
}
+1 -1
View File
@@ -6,4 +6,4 @@ class Foo {
val x = Foo::bar
// REF:Foo::bar
// RESULT:KtLightAnnotationMethod:bar
// RESULT:KtLightMethodImpl:bar
@@ -14,7 +14,7 @@ UFile (package = ) [public abstract interface Callback {...]
UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) [<init>()] : PsiType:UnsupportedOperationException
UIdentifier (Identifier (UnsupportedOperationException)) [UIdentifier (Identifier (UnsupportedOperationException))]
USimpleNameReferenceExpression (identifier = <init>) [<init>] : PsiType:UnsupportedOperationException
UMethod (name = Model) [public fun Model() {...}]
UAnnotationMethod (name = Model) [public fun Model() {...}]
UBlockExpression [{...}]
UBlockExpression [{...}] : PsiType:Unit
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 2)) [crashMe(Callback.java, { ...})] : PsiType:Unit