Light classes: do not rely on dummy context when data class autogenerated members conflict with declared members
Fix related issues with nested classes
This commit is contained in:
+20
@@ -0,0 +1,20 @@
|
||||
// p.Wrapper
|
||||
package p
|
||||
|
||||
class Wrapper {
|
||||
data class Equals(val code: G) {
|
||||
override fun equals(other: Any?): Boolean = true
|
||||
}
|
||||
|
||||
data class HashCode(val code: G) {
|
||||
override fun hashCode() = 3
|
||||
}
|
||||
|
||||
data class ToString(val code: G) {
|
||||
override fun toString() = "b"
|
||||
}
|
||||
}
|
||||
|
||||
class G
|
||||
|
||||
// LAZINESS:NoLaziness
|
||||
@@ -0,0 +1,13 @@
|
||||
public final class B {
|
||||
public B() { /* compiled code */ }
|
||||
|
||||
public static final class A implements p.I {
|
||||
private final p.I f;
|
||||
|
||||
public A(@org.jetbrains.annotations.NotNull p.I f) { /* compiled code */ }
|
||||
|
||||
public void f() { /* compiled code */ }
|
||||
|
||||
public void g() { /* compiled code */ }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
// p.B
|
||||
package p
|
||||
|
||||
class B {
|
||||
class A(private val f: I) : I by f {
|
||||
}
|
||||
}
|
||||
|
||||
interface I {
|
||||
fun g()
|
||||
|
||||
fun f()
|
||||
}
|
||||
|
||||
// LAZINESS:NoLaziness
|
||||
@@ -42,6 +42,18 @@ public class CompilerLightClassTestGenerated extends AbstractCompilerLightClassT
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("DataClassWithCustomImplementedMembers.kt")
|
||||
public void testDataClassWithCustomImplementedMembers() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/asJava/lightClasses/DataClassWithCustomImplementedMembers.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("DelegatedNested.kt")
|
||||
public void testDelegatedNested() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/asJava/lightClasses/DelegatedNested.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("Delegation.kt")
|
||||
public void testDelegation() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/asJava/lightClasses/Delegation.kt");
|
||||
|
||||
+2
-3
@@ -47,6 +47,7 @@ import org.jetbrains.kotlin.idea.decompiler.navigation.SourceNavigationHelper
|
||||
import org.jetbrains.kotlin.idea.stubindex.*
|
||||
import org.jetbrains.kotlin.idea.stubindex.KotlinSourceFilterScope.Companion.sourceAndClassFiles
|
||||
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
@@ -70,12 +71,10 @@ class IDELightClassGenerationSupport(private val project: Project) : LightClassG
|
||||
)
|
||||
}
|
||||
else {
|
||||
val hasDelegatedMembers = classOrObject.superTypeListEntries.any { it is KtDelegatedSuperTypeEntry }
|
||||
val dummyContextProvider = { IDELightClassContexts.lightContextForClassOrObject(classOrObject) }
|
||||
LazyLightClassDataHolder.ForClass(
|
||||
builder,
|
||||
exactContextProvider = { IDELightClassContexts.contextForNonLocalClassOrObject(classOrObject) },
|
||||
dummyContextProvider = if (!hasDelegatedMembers) dummyContextProvider else null
|
||||
dummyContextProvider = { IDELightClassContexts.lightContextForClassOrObject(classOrObject) }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+22
-2
@@ -125,7 +125,9 @@ object IDELightClassContexts {
|
||||
return IDELightClassConstructionContext(resolveSession.bindingContext, resolveSession.moduleDescriptor, EXACT)
|
||||
}
|
||||
|
||||
fun lightContextForClassOrObject(classOrObject: KtClassOrObject): LightClassConstructionContext {
|
||||
fun lightContextForClassOrObject(classOrObject: KtClassOrObject): LightClassConstructionContext? {
|
||||
if (!isDummyResolveApplicable(classOrObject)) return null
|
||||
|
||||
val resolveSession = setupAdHocResolve(classOrObject.project, classOrObject.getResolutionFacade().moduleDescriptor, listOf(classOrObject.containingKtFile))
|
||||
|
||||
ForceResolveUtil.forceResolveAllContents(resolveSession.resolveToDescriptor(classOrObject))
|
||||
@@ -133,6 +135,24 @@ object IDELightClassContexts {
|
||||
return IDELightClassConstructionContext(resolveSession.bindingContext, resolveSession.moduleDescriptor, LIGHT)
|
||||
}
|
||||
|
||||
private fun isDummyResolveApplicable(classOrObject: KtClassOrObject): Boolean {
|
||||
val hasDelegatedMembers = classOrObject.superTypeListEntries.any { it is KtDelegatedSuperTypeEntry }
|
||||
val dataClassWithGeneratedMembersOverridden = classOrObject.declarations.filterIsInstance<KtFunction>().any {
|
||||
isGeneratedForDataClass(it.nameAsSafeName)
|
||||
}
|
||||
return !hasDelegatedMembers && !dataClassWithGeneratedMembersOverridden
|
||||
&& classOrObject.declarations.filterIsInstance<KtClassOrObject>().all { isDummyResolveApplicable(it) }
|
||||
}
|
||||
|
||||
private fun isGeneratedForDataClass(name: Name): Boolean {
|
||||
return name == DataClassDescriptorResolver.EQUALS_METHOD_NAME ||
|
||||
// known failure is related to equals override, checking for other methods 'just in case'
|
||||
name == DataClassDescriptorResolver.COPY_METHOD_NAME ||
|
||||
name == DataClassDescriptorResolver.HASH_CODE_METHOD_NAME ||
|
||||
name == DataClassDescriptorResolver.TO_STRING_METHOD_NAME ||
|
||||
DataClassDescriptorResolver.isComponentLike(name)
|
||||
}
|
||||
|
||||
fun lightContextForFacade(files: List<KtFile>): LightClassConstructionContext {
|
||||
val representativeFile = files.first()
|
||||
val resolveSession = setupAdHocResolve(representativeFile.project, representativeFile.getResolutionFacade().moduleDescriptor, files)
|
||||
@@ -329,6 +349,6 @@ object IDELightClassContexts {
|
||||
}
|
||||
|
||||
private val notImplemented: Nothing
|
||||
get() = error("Should not be called")
|
||||
get() = error("Should not be called")
|
||||
}
|
||||
|
||||
|
||||
+7
-6
@@ -38,12 +38,13 @@ import org.jetbrains.kotlin.psi.KtCallableDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
||||
|
||||
typealias LightClassContextProvider = () -> LightClassConstructionContext
|
||||
typealias ExactLightClassContextProvider = () -> LightClassConstructionContext
|
||||
typealias DummyLightClassContextProvider = (() -> LightClassConstructionContext?)?
|
||||
|
||||
sealed class LazyLightClassDataHolder(
|
||||
builder: LightClassBuilder,
|
||||
exactContextProvider: LightClassContextProvider,
|
||||
dummyContextProvider: LightClassContextProvider?
|
||||
exactContextProvider: ExactLightClassContextProvider,
|
||||
dummyContextProvider: DummyLightClassContextProvider
|
||||
) : LightClassDataHolder {
|
||||
|
||||
private val exactResultLazyValue = lazyPub { builder(exactContextProvider()) }
|
||||
@@ -51,7 +52,7 @@ sealed class LazyLightClassDataHolder(
|
||||
private val exactResult: LightClassBuilderResult by exactResultLazyValue
|
||||
|
||||
private val lazyInexactResult by lazyPub {
|
||||
dummyContextProvider?.let { builder.invoke(it()) }
|
||||
dummyContextProvider?.let { provider -> provider()?.let { context -> builder.invoke(context) } }
|
||||
}
|
||||
|
||||
private val inexactResult: LightClassBuilderResult?
|
||||
@@ -67,7 +68,7 @@ sealed class LazyLightClassDataHolder(
|
||||
}
|
||||
|
||||
class ForClass(
|
||||
builder: LightClassBuilder, exactContextProvider: LightClassContextProvider, dummyContextProvider: LightClassContextProvider?
|
||||
builder: LightClassBuilder, exactContextProvider: ExactLightClassContextProvider, dummyContextProvider: DummyLightClassContextProvider
|
||||
) : LazyLightClassDataHolder(builder, exactContextProvider, dummyContextProvider), LightClassDataHolder.ForClass {
|
||||
override fun findDataForClassOrObject(classOrObject: KtClassOrObject): LightClassData =
|
||||
LazyLightClassData(relyOnDummySupertypes = classOrObject.getSuperTypeList() == null) { lightClassBuilderResult ->
|
||||
@@ -76,7 +77,7 @@ sealed class LazyLightClassDataHolder(
|
||||
}
|
||||
|
||||
class ForFacade(
|
||||
builder: LightClassBuilder, exactContextProvider: LightClassContextProvider, dummyContextProvider: LightClassContextProvider?
|
||||
builder: LightClassBuilder, exactContextProvider: ExactLightClassContextProvider, dummyContextProvider: DummyLightClassContextProvider
|
||||
) : LazyLightClassDataHolder(builder, exactContextProvider, dummyContextProvider), LightClassDataHolder.ForFacade
|
||||
|
||||
private inner class LazyLightClassData(
|
||||
|
||||
+12
@@ -42,6 +42,18 @@ public class IdeCompiledLightClassTestGenerated extends AbstractIdeCompiledLight
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("DataClassWithCustomImplementedMembers.kt")
|
||||
public void testDataClassWithCustomImplementedMembers() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/asJava/lightClasses/DataClassWithCustomImplementedMembers.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("DelegatedNested.kt")
|
||||
public void testDelegatedNested() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/asJava/lightClasses/DelegatedNested.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("Delegation.kt")
|
||||
public void testDelegation() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/asJava/lightClasses/Delegation.kt");
|
||||
|
||||
@@ -42,6 +42,18 @@ public class IdeLightClassTestGenerated extends AbstractIdeLightClassTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("DataClassWithCustomImplementedMembers.kt")
|
||||
public void testDataClassWithCustomImplementedMembers() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/asJava/lightClasses/DataClassWithCustomImplementedMembers.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("DelegatedNested.kt")
|
||||
public void testDelegatedNested() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/asJava/lightClasses/DelegatedNested.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("Delegation.kt")
|
||||
public void testDelegation() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/asJava/lightClasses/Delegation.kt");
|
||||
|
||||
Reference in New Issue
Block a user