Light class builder: do not generate methods delegating to DefaultImpls in kotlin classes

Class APIs from java point of view stays the same so we can avoid generating those methods
Otherwise we have to calculate all supertypes when getMethods() is called,
    which imposes severe performance penalties
We have to pretend these methods are not 'abstract' (also we consider them 'default' for safety)
    so java highlighting does not report "class should be abstract" for all inheritors
We have to manually report "class should be abstract" on some of the java inheritors,
    specifically those that are implementing interfaces directly
	    as opposed to extending kotlin classes implementing those interfaces
This commit is contained in:
Pavel V. Talanov
2017-03-30 17:44:19 +03:00
parent db294da24d
commit 4f701285b1
38 changed files with 510 additions and 45 deletions
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.asJava.elements
import com.intellij.psi.*
import com.intellij.psi.impl.PsiVariableEx
import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind
@@ -33,6 +34,8 @@ interface KtLightDeclaration<out T : KtDeclaration, out D : PsiElement> : KtLigh
interface KtLightMember<out D : PsiMember> : PsiMember, KtLightDeclaration<KtDeclaration, D>, PsiNameIdentifierOwner, PsiDocCommentOwner {
val lightMemberOrigin: LightMemberOrigin?
override fun getContainingClass(): KtLightClass
}
interface KtLightField : PsiField, KtLightMember<PsiField>, PsiVariableEx
@@ -40,5 +43,5 @@ interface KtLightField : PsiField, KtLightMember<PsiField>, PsiVariableEx
interface KtLightMethod : PsiAnnotationMethod, KtLightMember<PsiMethod> {
val isDelegated: Boolean
get() = lightMemberOrigin?.originKind == JvmDeclarationOriginKind.DELEGATION
|| lightMemberOrigin?.originKind == JvmDeclarationOriginKind.DELEGATION_TO_DEFAULT_IMPLS
|| lightMemberOrigin?.originKind == JvmDeclarationOriginKind.CLASS_MEMBER_DELEGATION_TO_DEFAULT_IMPL
}
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtNamedDeclaration
import org.jetbrains.kotlin.psi.psiUtil.hasBody
abstract class KtLightMemberImpl<out D : PsiMember>(
computeRealDelegate: () -> D,
@@ -104,18 +105,24 @@ class KtLightModifierList(
private val clsDelegate by lazyPub { owner.clsDelegate.modifierList!! }
private val _annotations by lazyPub { computeAnnotations(this, clsDelegate) }
override fun hasModifierProperty(name: String): Boolean {
if (dummyDelegate != null) {
if (name in visibilityModifiers) {
if (owner.kotlinOrigin?.hasModifier(KtTokens.OVERRIDE_KEYWORD) ?: false) {
return clsDelegate.hasModifierProperty(name)
}
override fun hasModifierProperty(name: String) = when {
name == PsiModifier.ABSTRACT && isImplementationInInterface() -> false
name == PsiModifier.DEFAULT && isImplementationInInterface() -> true
dummyDelegate != null -> {
when {
name in visibilityModifiers && isOverride() ->
clsDelegate.hasModifierProperty(name)
else -> dummyDelegate.hasModifierProperty(name)
}
return dummyDelegate.hasModifierProperty(name)
}
return clsDelegate.hasModifierProperty(name)
else -> clsDelegate.hasModifierProperty(name)
}
private fun isOverride() = owner.kotlinOrigin?.hasModifier(KtTokens.OVERRIDE_KEYWORD) ?: false
private fun isImplementationInInterface()
= owner.containingClass.isInterface && owner is KtLightMethod && owner.kotlinOrigin?.hasBody() ?: false
override fun hasExplicitModifier(name: String) = hasModifierProperty(name)
override fun setModifierProperty(name: String, value: Boolean) = clsDelegate.setModifierProperty(name, value)