KtLightClassForSourceDeclaration: use psi based resolve to speedup isInheritor checks
This commit is contained in:
+64
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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.kotlin.idea.caches.resolve.lightClasses
|
||||
|
||||
import com.intellij.psi.CommonClassNames
|
||||
import com.intellij.psi.PsiClass
|
||||
import org.jetbrains.kotlin.asJava.ImpreciseResolveResult
|
||||
import org.jetbrains.kotlin.asJava.ImpreciseResolveResult.*
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration
|
||||
import org.jetbrains.kotlin.asJava.classes.LightClassInheritanceHelper
|
||||
import org.jetbrains.kotlin.asJava.classes.defaultJavaAncestorQualifiedName
|
||||
import org.jetbrains.kotlin.idea.search.PsiBasedClassResolver
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
|
||||
class IdeLightClassInheritanceHelper : LightClassInheritanceHelper {
|
||||
override fun isInheritor(
|
||||
lightClass: KtLightClassForSourceDeclaration,
|
||||
baseClass: PsiClass,
|
||||
checkDeep: Boolean
|
||||
): ImpreciseResolveResult {
|
||||
val classOrObject = lightClass.kotlinOrigin
|
||||
val entries = classOrObject.superTypeListEntries
|
||||
val hasSuperClass = entries.any { it is KtSuperTypeCallEntry }
|
||||
if (baseClass.qualifiedName == classOrObject.defaultJavaAncestorQualifiedName() && (!hasSuperClass || checkDeep)) {
|
||||
return MATCH
|
||||
}
|
||||
if (checkDeep && baseClass.qualifiedName == CommonClassNames.JAVA_LANG_OBJECT) {
|
||||
return MATCH
|
||||
}
|
||||
val amongEntries = isAmongEntries(baseClass, entries)
|
||||
return when {
|
||||
!checkDeep -> amongEntries
|
||||
amongEntries == MATCH -> MATCH
|
||||
else -> UNSURE
|
||||
}
|
||||
}
|
||||
|
||||
private fun isAmongEntries(baseClass: PsiClass, entries: List<KtSuperTypeListEntry>): ImpreciseResolveResult {
|
||||
val psiBasedResolver = PsiBasedClassResolver(baseClass)
|
||||
entries@ for (entry in entries) {
|
||||
val reference: KtSimpleNameExpression = entry.typeAsUserType?.referenceExpression ?: continue@entries
|
||||
when (psiBasedResolver.canBeTargetReference(reference)) {
|
||||
MATCH -> return MATCH
|
||||
NO_MATCH -> continue@entries
|
||||
UNSURE -> return UNSURE
|
||||
}
|
||||
}
|
||||
return NO_MATCH
|
||||
}
|
||||
}
|
||||
+4
-11
@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.idea.caches.resolve.lightClasses
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.Key
|
||||
import com.intellij.psi.PsiClass
|
||||
import com.intellij.psi.PsiClassType
|
||||
import com.intellij.psi.PsiMember
|
||||
import com.intellij.psi.PsiMethod
|
||||
import com.intellij.psi.impl.java.stubs.PsiJavaFileStub
|
||||
@@ -65,7 +64,7 @@ sealed class LazyLightClassDataHolder(
|
||||
|
||||
// for facade or defaultImpls
|
||||
override fun findData(findDelegate: (PsiJavaFileStub) -> PsiClass): LightClassData =
|
||||
LazyLightClassData(relyOnDummySupertypes = true) { lightClassBuilderResult ->
|
||||
LazyLightClassData { lightClassBuilderResult ->
|
||||
findDelegate(lightClassBuilderResult.stub)
|
||||
}
|
||||
|
||||
@@ -73,7 +72,7 @@ sealed class LazyLightClassDataHolder(
|
||||
builder: LightClassBuilder, exactContextProvider: ExactLightClassContextProvider, dummyContextProvider: DummyLightClassContextProvider
|
||||
) : LazyLightClassDataHolder(builder, exactContextProvider, dummyContextProvider), LightClassDataHolder.ForClass {
|
||||
override fun findDataForClassOrObject(classOrObject: KtClassOrObject): LightClassData =
|
||||
LazyLightClassData(relyOnDummySupertypes = classOrObject.getSuperTypeList() == null) { lightClassBuilderResult ->
|
||||
LazyLightClassData { lightClassBuilderResult ->
|
||||
lightClassBuilderResult.stub.findDelegate(classOrObject)
|
||||
}
|
||||
}
|
||||
@@ -83,7 +82,6 @@ sealed class LazyLightClassDataHolder(
|
||||
) : LazyLightClassDataHolder(builder, exactContextProvider, dummyContextProvider), LightClassDataHolder.ForFacade
|
||||
|
||||
private inner class LazyLightClassData(
|
||||
private val relyOnDummySupertypes: Boolean,
|
||||
findDelegate: (LightClassBuilderResult) -> PsiClass
|
||||
) : LightClassData {
|
||||
override val clsDelegate: PsiClass by lazyPub { findDelegate(exactResult) }
|
||||
@@ -133,17 +131,13 @@ sealed class LazyLightClassDataHolder(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override val supertypes: Array<PsiClassType>
|
||||
get() = if (relyOnDummySupertypes && dummyDelegate != null) dummyDelegate!!.superTypes else clsDelegate.superTypes
|
||||
|
||||
}
|
||||
|
||||
private fun <T : PsiMember> T?.assertMatches(dummyMember: T, containingClass: KtLightClass): T {
|
||||
if (this == null) throw LazyLightClassMemberMatchingError.NoMatch(dummyMember, containingClass)
|
||||
|
||||
val parameterCountMatches = (this as? PsiMethod)?.parameterList?.parametersCount ?: 0 ==
|
||||
(dummyMember as? PsiMethod)?.parameterList?.parametersCount ?: 0
|
||||
(dummyMember as? PsiMethod)?.parameterList?.parametersCount ?: 0
|
||||
if (this.memberIndex != dummyMember.memberIndex || !parameterCountMatches) {
|
||||
throw LazyLightClassMemberMatchingError.WrongMatch(this, dummyMember, containingClass)
|
||||
}
|
||||
@@ -157,7 +151,6 @@ private fun shouldRollbackOptimization(origin: LightMemberOriginForDeclaration?)
|
||||
|
||||
if (!kotlinDeclaration.hasModifier(KtTokens.OVERRIDE_KEYWORD)) return false
|
||||
|
||||
|
||||
val possiblyOverridesInternalMember = kotlinDeclaration.name?.let { anyInternalMembersWithThisName(it, kotlinDeclaration.project) } ?: false
|
||||
return possiblyOverridesInternalMember
|
||||
}
|
||||
@@ -194,4 +187,4 @@ private sealed class LazyLightClassMemberMatchingError(message: String, containi
|
||||
private val PsiMember.debugName
|
||||
get() = "${this::class.java.simpleName}:${this.name} ${this.memberIndex}" + if (this is PsiMethod) " (with ${parameterList.parametersCount} parameters)" else ""
|
||||
|
||||
var KtClassOrObject.hasLightClassMatchingErrors: Boolean by NotNullableUserDataProperty(Key.create("LIGHT_CLASS_MATCHING_ERRORS"), false)
|
||||
var KtClassOrObject.hasLightClassMatchingErrors: Boolean by NotNullableUserDataProperty(Key.create("LIGHT_CLASS_MATCHING_ERRORS"), false)
|
||||
|
||||
Reference in New Issue
Block a user