Do not generate DefaultImpls for light classes if not needed

#KT-41130 In Progress
This commit is contained in:
Mikhail Zarechenskiy
2021-03-09 14:45:31 +03:00
committed by TeamCityServer
parent ac6232b4ba
commit 111e54c8c1
17 changed files with 98 additions and 23 deletions
@@ -13,6 +13,7 @@ import com.intellij.psi.search.PsiSearchScopeUtil
import com.intellij.util.SmartList
import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport
import org.jetbrains.kotlin.asJava.classes.*
import org.jetbrains.kotlin.config.JvmAnalysisFlags
import org.jetbrains.kotlin.descriptors.PackageViewDescriptor
import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName
import org.jetbrains.kotlin.load.java.components.FilesByFacadeFqNameIndexer
@@ -109,7 +110,7 @@ class CliKotlinAsJavaSupport(
}
override fun getLightClass(classOrObject: KtClassOrObject): KtLightClass? =
KtLightClassForSourceDeclaration.create(classOrObject)
KtLightClassForSourceDeclaration.create(classOrObject, traceHolder.languageVersionSettings.getFlag(JvmAnalysisFlags.jvmDefaultMode))
override fun getLightClassForScript(script: KtScript): KtLightClassForScript? =
KtLightClassForScript.create(script)
@@ -19,11 +19,12 @@ package org.jetbrains.kotlin.asJava.classes
import com.intellij.psi.*
import com.intellij.util.IncorrectOperationException
import org.jetbrains.kotlin.asJava.builder.LightClassData
import org.jetbrains.kotlin.config.JvmDefaultMode
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.psi.KtClassOrObject
class KtLightClassForInterfaceDefaultImpls(classOrObject: KtClassOrObject)
: KtLightClassForSourceDeclaration(classOrObject) {
: KtLightClassForSourceDeclaration(classOrObject, JvmDefaultMode.DEFAULT) {
override fun getQualifiedName(): String? = containingClass?.qualifiedName?.let { it + ".${JvmAbi.DEFAULT_IMPLS_CLASS_NAME}" }
override fun getName() = JvmAbi.DEFAULT_IMPLS_CLASS_NAME
@@ -54,7 +55,7 @@ class KtLightClassForInterfaceDefaultImpls(classOrObject: KtClassOrObject)
throw IncorrectOperationException("Impossible to rename DefaultImpls")
}
override fun getContainingClass() = KtLightClassForSourceDeclaration.create(classOrObject)
override fun getContainingClass() = KtLightClassForSourceDeclaration.create(classOrObject, JvmDefaultMode.DEFAULT)
override fun getOwnInnerClasses() = emptyList<PsiClass>()
}
@@ -12,13 +12,14 @@ import com.intellij.psi.impl.light.LightClass
import com.intellij.psi.impl.light.LightMethod
import org.jetbrains.kotlin.asJava.LightClassUtil
import org.jetbrains.kotlin.asJava.toLightClass
import org.jetbrains.kotlin.config.JvmDefaultMode
import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
open class KtLightClassForLocalDeclaration(
classOrObject: KtClassOrObject
) : KtLightClassForSourceDeclaration(classOrObject) {
) : KtLightClassForSourceDeclaration(classOrObject, JvmDefaultMode.DEFAULT) {
override fun copy(): PsiElement = KtLightClassForLocalDeclaration(classOrObject.copy() as KtClassOrObject)
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.asJava.builder.LightClassData
import org.jetbrains.kotlin.asJava.builder.LightClassDataHolder
import org.jetbrains.kotlin.asJava.builder.LightClassDataProviderForScript
import org.jetbrains.kotlin.asJava.elements.FakeFileForLightClass
import org.jetbrains.kotlin.config.JvmDefaultMode
import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.load.java.structure.LightClassOriginKind
import org.jetbrains.kotlin.name.FqName
@@ -107,7 +108,7 @@ open class KtLightClassForScript(val script: KtScript) : KtLazyLightClass(script
// inner classes with null names can't be searched for and can't be used from java anyway
// we can't prohibit creating light classes with null names either since they can contain members
.filter { it.name != null }
.mapNotNull { KtLightClassForSourceDeclaration.create(it) }
.mapNotNull { KtLightClassForSourceDeclaration.create(it, JvmDefaultMode.DEFAULT) }
}
override fun getInitializers(): Array<PsiClassInitializer> = PsiClassInitializer.EMPTY_ARRAY
@@ -41,6 +41,7 @@ import org.jetbrains.kotlin.asJava.elements.KtLightModifierList
import org.jetbrains.kotlin.asJava.elements.KtLightPsiReferenceList
import org.jetbrains.kotlin.asJava.hasInterfaceDefaultImpls
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
import org.jetbrains.kotlin.config.JvmDefaultMode
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.lexer.KtTokens.*
import org.jetbrains.kotlin.load.java.structure.LightClassOriginKind
@@ -67,6 +68,7 @@ private class KtLightClassModifierList(containingClass: KtLightClassForSourceDec
abstract class KtLightClassForSourceDeclaration(
protected val classOrObject: KtClassOrObject,
protected val jvmDefaultMode: JvmDefaultMode,
private val forceUsingOldLightClasses: Boolean = false
) : KtLazyLightClass(classOrObject.manager),
StubBasedPsiElement<KotlinClassOrObjectStub<out KtClassOrObject>> {
@@ -123,7 +125,7 @@ abstract class KtLightClassForSourceDeclaration(
private val _containingFile: PsiFile by lazyPub {
object : FakeFileForLightClass(
classOrObject.containingKtFile,
{ if (classOrObject.isTopLevel()) this else create(getOutermostClassOrObject(classOrObject))!! },
{ if (classOrObject.isTopLevel()) this else create(getOutermostClassOrObject(classOrObject), jvmDefaultMode)!! },
{ getJavaFileStub() }
) {
override fun findReferenceAt(offset: Int) = ktFile.findReferenceAt(offset)
@@ -179,7 +181,7 @@ abstract class KtLightClassForSourceDeclaration(
val containingClassOrObject = (classOrObject.parent as? KtClassBody)?.parent as? KtClassOrObject
if (containingClassOrObject != null) {
return create(containingClassOrObject)
return create(containingClassOrObject, jvmDefaultMode)
}
// TODO: should return null
@@ -300,12 +302,12 @@ abstract class KtLightClassForSourceDeclaration(
.filter { it.name != null }
.mapNotNullTo(result) {
if (!forceUsingOldLightClasses)
create(it)
create(it, jvmDefaultMode)
else
createNoCache(it, forceUsingOldLightClasses = true)
createNoCache(it, jvmDefaultMode, forceUsingOldLightClasses = true)
}
if (classOrObject.hasInterfaceDefaultImpls) {
if (classOrObject.hasInterfaceDefaultImpls && jvmDefaultMode != JvmDefaultMode.ALL_INCOMPATIBLE) {
result.add(KtLightClassForInterfaceDefaultImpls(classOrObject))
}
return result
@@ -335,16 +337,20 @@ abstract class KtLightClassForSourceDeclaration(
FINAL_KEYWORD to PsiModifier.FINAL
)
fun create(classOrObject: KtClassOrObject): KtLightClassForSourceDeclaration? =
fun create(classOrObject: KtClassOrObject, jvmDefaultMode: JvmDefaultMode): KtLightClassForSourceDeclaration? =
CachedValuesManager.getCachedValue(classOrObject) {
CachedValueProvider.Result
.create(
createNoCache(classOrObject, KtUltraLightSupport.forceUsingOldLightClasses),
createNoCache(classOrObject, jvmDefaultMode, KtUltraLightSupport.forceUsingOldLightClasses),
KotlinModificationTrackerService.getInstance(classOrObject.project).outOfBlockModificationTracker
)
}
fun createNoCache(classOrObject: KtClassOrObject, forceUsingOldLightClasses: Boolean): KtLightClassForSourceDeclaration? {
fun createNoCache(
classOrObject: KtClassOrObject,
jvmDefaultMode: JvmDefaultMode,
forceUsingOldLightClasses: Boolean
): KtLightClassForSourceDeclaration? {
val containingFile = classOrObject.containingFile
if (containingFile is KtCodeFragment) {
// Avoid building light classes for code fragments
@@ -372,7 +378,7 @@ abstract class KtLightClassForSourceDeclaration(
KtLightClassForLocalDeclaration(classOrObject)
else ->
KtLightClassImpl(classOrObject, forceUsingOldLightClasses)
KtLightClassImpl(classOrObject, jvmDefaultMode, forceUsingOldLightClasses)
}
}
@@ -16,13 +16,15 @@
package org.jetbrains.kotlin.asJava.classes
import org.jetbrains.kotlin.config.JvmDefaultMode
import org.jetbrains.kotlin.psi.KtClassOrObject
// light class for top level or (inner/nested of top level) source declarations
open class KtLightClassImpl @JvmOverloads constructor(
classOrObject: KtClassOrObject,
jvmDefaultMode: JvmDefaultMode,
forceUsingOldLightClasses: Boolean = false
) : KtLightClassForSourceDeclaration(classOrObject, forceUsingOldLightClasses) {
) : KtLightClassForSourceDeclaration(classOrObject, jvmDefaultMode, forceUsingOldLightClasses) {
override fun getQualifiedName() = classOrObject.fqName?.asString()
override fun getParent() = if (classOrObject.isTopLevel())
@@ -30,5 +32,5 @@ open class KtLightClassImpl @JvmOverloads constructor(
else
containingClass
override fun copy() = KtLightClassImpl(classOrObject.copy() as KtClassOrObject)
override fun copy() = KtLightClassImpl(classOrObject.copy() as KtClassOrObject, jvmDefaultMode)
}
@@ -24,6 +24,8 @@ import org.jetbrains.kotlin.backend.common.DataClassMethodGenerator
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.codegen.JvmCodegenUtil
import org.jetbrains.kotlin.codegen.kotlinType
import org.jetbrains.kotlin.config.AnalysisFlags
import org.jetbrains.kotlin.config.JvmAnalysisFlags
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
@@ -46,7 +48,7 @@ import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.typeUtil.isAnyOrNullableAny
open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val support: KtUltraLightSupport) :
KtLightClassImpl(classOrObject) {
KtLightClassImpl(classOrObject, support.languageVersionSettings.getFlag(JvmAnalysisFlags.jvmDefaultMode)) {
private class KtUltraLightClassModifierList(
private val containingClass: KtLightClassForSourceDeclaration,
@@ -484,7 +486,7 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
val containingBody = classOrObject.parent as? KtClassBody
val containingClass = containingBody?.parent as? KtClassOrObject
containingClass?.let { return create(it) }
containingClass?.let { return create(it, jvmDefaultMode) }
val containingBlock = classOrObject.parent as? KtBlockExpression
val containingScript = containingBlock?.parent as? KtScript
@@ -26,7 +26,6 @@ import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.hasExpectModifier
import org.jetbrains.kotlin.psi.psiUtil.hasSuspendModifier
import org.jetbrains.kotlin.psi.psiUtil.isPrivate
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.isPublishedApi
@@ -0,0 +1,6 @@
public abstract interface KtInterface /* KtInterface*/ {
public abstract void defaultFun();// defaultFun()
public abstract void withoutBody();// withoutBody()
}
@@ -0,0 +1,10 @@
// CHECK_BY_JAVA_FILE
// COMPILER_ARGUMENTS: -Xjvm-default=all
interface KtInterface {
fun defaultFun() {
println("default")
}
fun withoutBody()
}
@@ -0,0 +1,9 @@
public abstract interface KtInterface /* KtInterface*/ {
public abstract void defaultFun();// defaultFun()
public abstract void withoutBody();// withoutBody()
class DefaultImpls ...
}
@@ -0,0 +1,10 @@
// CHECK_BY_JAVA_FILE
// COMPILER_ARGUMENTS: -Xjvm-default=all-compatibility
interface KtInterface {
fun defaultFun() {
println("default")
}
fun withoutBody()
}
@@ -16,6 +16,7 @@ import com.intellij.util.SmartList
import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport
import org.jetbrains.kotlin.asJava.builder.ClsWrapperStubPsiFactory
import org.jetbrains.kotlin.asJava.classes.*
import org.jetbrains.kotlin.config.JvmAnalysisFlags
import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName
import org.jetbrains.kotlin.idea.caches.lightClasses.ClsJavaStubByVirtualFileCache
import org.jetbrains.kotlin.idea.caches.lightClasses.KtLightClassForDecompiledDeclaration
@@ -24,6 +25,7 @@ import org.jetbrains.kotlin.idea.caches.project.*
import org.jetbrains.kotlin.idea.caches.project.IdeaModuleInfo
import org.jetbrains.kotlin.idea.decompiler.classFile.KtClsFile
import org.jetbrains.kotlin.idea.decompiler.navigation.SourceNavigationHelper
import org.jetbrains.kotlin.idea.project.getLanguageVersionSettings
import org.jetbrains.kotlin.idea.project.platform
import org.jetbrains.kotlin.idea.stubindex.*
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
@@ -38,9 +40,10 @@ import org.jetbrains.kotlin.utils.sure
open class IDEKotlinAsJavaSupport(private val project: Project) : KotlinAsJavaSupport() {
private val psiManager: PsiManager = PsiManager.getInstance(project)
private val languageVersionSettings = project.getLanguageVersionSettings()
protected open fun createLightClassForSourceDeclaration(classOrObject: KtClassOrObject): KtLightClass? =
KtLightClassForSourceDeclaration.create(classOrObject)
KtLightClassForSourceDeclaration.create(classOrObject, languageVersionSettings.getFlag(JvmAnalysisFlags.jvmDefaultMode))
protected open fun createLightClassForScript(script: KtScript): KtLightClass? =
KtLightClassForScript.create(script)
@@ -64,6 +64,16 @@ public class FirClassLoadingTestGenerated extends AbstractFirClassLoadingTest {
runTest("compiler/testData/asJava/ultraLightClasses/dataClasses.kt");
}
@TestMetadata("defaultMethodInKotlinWithSettingAll.kt")
public void testDefaultMethodInKotlinWithSettingAll() throws Exception {
runTest("compiler/testData/asJava/ultraLightClasses/defaultMethodInKotlinWithSettingAll.kt");
}
@TestMetadata("defaultMethodInKotlinWithSettingAllCompatibility.kt")
public void testDefaultMethodInKotlinWithSettingAllCompatibility() throws Exception {
runTest("compiler/testData/asJava/ultraLightClasses/defaultMethodInKotlinWithSettingAllCompatibility.kt");
}
@TestMetadata("delegatesWithAnnotations.kt")
public void testDelegatesWithAnnotations() throws Exception {
runTest("compiler/testData/asJava/ultraLightClasses/delegatesWithAnnotations.kt");
@@ -64,6 +64,16 @@ public class UltraLightClassLoadingTestGenerated extends AbstractUltraLightClass
runTest("compiler/testData/asJava/ultraLightClasses/dataClasses.kt");
}
@TestMetadata("defaultMethodInKotlinWithSettingAll.kt")
public void testDefaultMethodInKotlinWithSettingAll() throws Exception {
runTest("compiler/testData/asJava/ultraLightClasses/defaultMethodInKotlinWithSettingAll.kt");
}
@TestMetadata("defaultMethodInKotlinWithSettingAllCompatibility.kt")
public void testDefaultMethodInKotlinWithSettingAllCompatibility() throws Exception {
runTest("compiler/testData/asJava/ultraLightClasses/defaultMethodInKotlinWithSettingAllCompatibility.kt");
}
@TestMetadata("delegatesWithAnnotations.kt")
public void testDelegatesWithAnnotations() throws Exception {
runTest("compiler/testData/asJava/ultraLightClasses/delegatesWithAnnotations.kt");
@@ -11,6 +11,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.asJava.classes.KtLightClass;
import org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration;
import org.jetbrains.kotlin.config.JvmDefaultMode;
import org.jetbrains.kotlin.idea.caches.lightClasses.KtLightClassForDecompiledDeclaration;
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase;
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor;
@@ -49,8 +50,8 @@ public class LightClassEqualsTest extends KotlinLightCodeInsightFixtureTestCase
static void doTestEquals(@Nullable KtClassOrObject origin) {
assertNotNull(origin);
PsiClass lightClass1 = KtLightClassForSourceDeclaration.Companion.createNoCache(origin, true);
PsiClass lightClass2 = KtLightClassForSourceDeclaration.Companion.createNoCache(origin, true);
PsiClass lightClass1 = KtLightClassForSourceDeclaration.Companion.createNoCache(origin, JvmDefaultMode.DEFAULT, true);
PsiClass lightClass2 = KtLightClassForSourceDeclaration.Companion.createNoCache(origin, JvmDefaultMode.DEFAULT, true);
assertNotNull(lightClass1);
assertNotNull(lightClass2);
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
import org.jetbrains.kotlin.asJava.PsiClassRenderer
import org.jetbrains.kotlin.asJava.PsiClassRenderer.renderClass
import org.jetbrains.kotlin.asJava.classes.*
import org.jetbrains.kotlin.config.JvmAnalysisFlags
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.idea.project.languageVersionSettings
@@ -104,7 +105,9 @@ object UltraLightChecker {
}
fun checkClassEquivalence(ktClass: KtClassOrObject): KtUltraLightClass? {
val gold = KtLightClassForSourceDeclaration.createNoCache(ktClass, forceUsingOldLightClasses = true)
val gold = KtLightClassForSourceDeclaration.createNoCache(
ktClass, ktClass.languageVersionSettings.getFlag(JvmAnalysisFlags.jvmDefaultMode), forceUsingOldLightClasses = true
)
val ultraLightClass = LightClassGenerationSupport.getInstance(ktClass.project).createUltraLightClass(ktClass) ?: return null
val secondULInstance = LightClassGenerationSupport.getInstance(ktClass.project).createUltraLightClass(ktClass)