FIR: don't create delegated constructor call in expect

#KT-51756 Fixed
This commit is contained in:
Mikhail Glukhikh
2022-03-29 16:06:40 +03:00
parent 16027b4531
commit aaebb7a30e
12 changed files with 105 additions and 34 deletions
@@ -3225,6 +3225,12 @@ public class DiagnosisCompilerFirTestdataTestGenerated extends AbstractDiagnosis
runTest("compiler/fir/analysis-tests/testData/resolve/problems/doubleGenericDiamond.kt");
}
@Test
@TestMetadata("expectConstructor.kt")
public void testExpectConstructor() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/problems/expectConstructor.kt");
}
@Test
@TestMetadata("fakeTypeMismatchOnExtensionReference.kt")
public void testFakeTypeMismatchOnExtensionReference() throws Exception {
@@ -2844,6 +2844,11 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract
runTest("compiler/fir/analysis-tests/testData/resolve/problems/doubleGenericDiamond.kt");
}
@TestMetadata("expectConstructor.kt")
public void testExpectConstructor() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/problems/expectConstructor.kt");
}
@TestMetadata("fakeTypeMismatchOnExtensionReference.kt")
public void testFakeTypeMismatchOnExtensionReference() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/problems/fakeTypeMismatchOnExtensionReference.kt");
@@ -0,0 +1,31 @@
FILE: expectConstructor.kt
public open class Base : R|kotlin/Any| {
public constructor(v: R|kotlin/String|): R|Base| {
super<R|kotlin/Any|>()
}
}
public final expect class Derived : R|Base| {
public expect constructor(v: R|kotlin/String|): R|Derived|
}
public open expect class ExpectBase : R|kotlin/Any| {
public expect constructor(v: R|kotlin/String|): R|ExpectBase|
}
public final expect class ExpectDerived : R|ExpectBase| {
public expect constructor(v: R|kotlin/String|): R|ExpectDerived|
}
public open expect class IOException : R|kotlin/Any| {
public expect constructor(message: R|kotlin/String|, cause: R|kotlin/Throwable?|): R|IOException|
public expect constructor(message: R|kotlin/String|): R|IOException| {
super<R|kotlin/Any|>()
}
}
public final expect class EOFException : R|IOException| {
public expect constructor(message: R|kotlin/String|): R|EOFException|
}
@@ -0,0 +1,13 @@
open class Base(v: String)
expect class Derived(v: String) : Base
expect open class ExpectBase(v: String)
expect class ExpectDerived(v: String) : ExpectBase
expect open class IOException(message: String, cause: Throwable?) {
<!PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED!>constructor(message: String)<!>
}
expect class EOFException(message: String) : IOException
@@ -1,9 +1,7 @@
Module: m1-common
FILE: common.kt
public open expect class A<T> : R|kotlin/Any| {
public expect constructor<T>(): R|A<T>| {
super<R|kotlin/Any|>()
}
public expect constructor<T>(): R|A<T>|
public open expect fun foo(arg: R|T|): R|kotlin/Unit|
@@ -1,9 +1,7 @@
Module: m1-common
FILE: common.kt
public open expect class A : R|kotlin/Any| {
public expect constructor(): R|A| {
super<R|kotlin/Any|>()
}
public expect constructor(): R|A|
public final expect fun foo(): R|kotlin/Unit|
@@ -1,9 +1,7 @@
Module: m1-common
FILE: common.kt
public open expect class A : R|kotlin/Any| {
public expect constructor(): R|A| {
super<R|kotlin/Any|>()
}
public expect constructor(): R|A|
public final expect fun foo(): R|kotlin/Unit|
@@ -3225,6 +3225,12 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest {
runTest("compiler/fir/analysis-tests/testData/resolve/problems/doubleGenericDiamond.kt");
}
@Test
@TestMetadata("expectConstructor.kt")
public void testExpectConstructor() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/problems/expectConstructor.kt");
}
@Test
@TestMetadata("fakeTypeMismatchOnExtensionReference.kt")
public void testFakeTypeMismatchOnExtensionReference() throws Exception {
@@ -3225,6 +3225,12 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
runTest("compiler/fir/analysis-tests/testData/resolve/problems/doubleGenericDiamond.kt");
}
@Test
@TestMetadata("expectConstructor.kt")
public void testExpectConstructor() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/problems/expectConstructor.kt");
}
@Test
@TestMetadata("fakeTypeMismatchOnExtensionReference.kt")
public void testFakeTypeMismatchOnExtensionReference() throws Exception {
@@ -56,6 +56,7 @@ import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.lexer.KtTokens.*
import org.jetbrains.kotlin.name.*
import org.jetbrains.kotlin.utils.addToStdlib.runIf
import org.jetbrains.kotlin.utils.addToStdlib.runUnless
class DeclarationsConverter(
session: FirSession,
@@ -711,6 +712,7 @@ class DeclarationsConverter(
}
val enumEntryName = identifier.nameAsSafeName()
val containingClassIsExpectClass = classWrapper.hasExpect() || context.containerIsExpect
return buildEnumEntry {
source = enumEntry.toFirSourceElement()
moduleData = baseModuleData
@@ -720,7 +722,7 @@ class DeclarationsConverter(
symbol = FirEnumEntrySymbol(CallableId(context.currentClassId, enumEntryName))
status = FirDeclarationStatusImpl(Visibilities.Public, Modality.FINAL).apply {
isStatic = true
isExpect = classWrapper.hasExpect() || context.containerIsExpect
isExpect = containingClassIsExpectClass
}
if (classWrapper.hasDefaultConstructor && enumEntry.getChildNodeByType(INITIALIZER_LIST) == null &&
modifiers.annotations.isEmpty() && classBodyNode == null
@@ -762,7 +764,7 @@ class DeclarationsConverter(
enumClassWrapper,
superTypeCallEntry?.toFirSourceElement(),
isEnumEntry = true,
containingClassIsExpectClass = false
containingClassIsExpectClass = containingClassIsExpectClass
)?.let { declarations += it.firConstructor }
classBodyNode?.also {
// Use ANONYMOUS_OBJECT_NAME for the owner class id of enum entry declarations
@@ -828,7 +830,9 @@ class DeclarationsConverter(
): PrimaryConstructor? {
if (primaryConstructor == null && !classWrapper.isEnumEntry() && classWrapper.hasSecondaryConstructor) return null
val classKind = classWrapper.classBuilder.classKind
if (primaryConstructor == null && (containingClassIsExpectClass && classKind != ClassKind.ENUM_CLASS)) return null
if (primaryConstructor == null &&
(containingClassIsExpectClass && classKind != ClassKind.ENUM_CLASS && classKind != ClassKind.ENUM_ENTRY)
) return null
if (classWrapper.isInterface()) return null
var modifiers = Modifier()
@@ -841,26 +845,28 @@ class DeclarationsConverter(
}
val defaultVisibility = classWrapper.defaultConstructorVisibility()
val firDelegatedCall = buildDelegatedConstructorCall {
source = delegatedConstructorSource ?: selfTypeSource?.fakeElement(KtFakeSourceElementKind.DelegatingConstructorCall)
constructedTypeRef = classWrapper.delegatedSuperTypeRef.copyWithNewSourceKind(KtFakeSourceElementKind.ImplicitTypeRef)
isThis = false
calleeReference = buildExplicitSuperReference {
//[dirty] in case of enum classWrapper.delegatedSuperTypeRef.source is whole enum source
source = if (!isEnumEntry) {
classWrapper.delegatedSuperTypeRef.source?.fakeElement(KtFakeSourceElementKind.DelegatingConstructorCall)
?: this@buildDelegatedConstructorCall.source?.fakeElement(KtFakeSourceElementKind.DelegatingConstructorCall)
} else {
delegatedConstructorSource
?.lighterASTNode
?.getChildNodeByType(CONSTRUCTOR_CALLEE)
?.toFirSourceElement(KtFakeSourceElementKind.DelegatingConstructorCall)
?: this@buildDelegatedConstructorCall.source
}
val firDelegatedCall = runUnless(containingClassIsExpectClass) {
buildDelegatedConstructorCall {
source = delegatedConstructorSource ?: selfTypeSource?.fakeElement(KtFakeSourceElementKind.DelegatingConstructorCall)
constructedTypeRef = classWrapper.delegatedSuperTypeRef.copyWithNewSourceKind(KtFakeSourceElementKind.ImplicitTypeRef)
isThis = false
calleeReference = buildExplicitSuperReference {
//[dirty] in case of enum classWrapper.delegatedSuperTypeRef.source is whole enum source
source = if (!isEnumEntry) {
classWrapper.delegatedSuperTypeRef.source?.fakeElement(KtFakeSourceElementKind.DelegatingConstructorCall)
?: this@buildDelegatedConstructorCall.source?.fakeElement(KtFakeSourceElementKind.DelegatingConstructorCall)
} else {
delegatedConstructorSource
?.lighterASTNode
?.getChildNodeByType(CONSTRUCTOR_CALLEE)
?.toFirSourceElement(KtFakeSourceElementKind.DelegatingConstructorCall)
?: this@buildDelegatedConstructorCall.source
}
superTypeRef = this@buildDelegatedConstructorCall.constructedTypeRef
superTypeRef = this@buildDelegatedConstructorCall.constructedTypeRef
}
extractArgumentsFrom(classWrapper.superTypeCallEntry)
}
extractArgumentsFrom(classWrapper.superTypeCallEntry)
}
val explicitVisibility = runIf(primaryConstructor != null) {
@@ -837,6 +837,7 @@ open class RawFirBuilder(
delegatedSelfTypeRef ?: delegatedSuperTypeRef!!,
owner = this,
containerTypeParameters,
containingClassIsExpectClass,
body = null
)
container.declarations += firPrimaryConstructor
@@ -851,12 +852,13 @@ open class RawFirBuilder(
delegatedSelfTypeRef: FirTypeRef,
owner: KtClassOrObject,
ownerTypeParameters: List<FirTypeParameterRef>,
containingClassIsExpectClass: Boolean,
body: FirBlock? = null
): FirConstructor {
val constructorCall = superTypeCallEntry?.toFirSourceElement()
val constructorSource = this?.toFirSourceElement()
?: owner.toKtPsiSourceElement(KtFakeSourceElementKind.ImplicitConstructor)
val firDelegatedCall = buildDelegatedConstructorCall {
val firDelegatedCall = if (containingClassIsExpectClass) null else buildDelegatedConstructorCall {
source = constructorCall ?: constructorSource.fakeElement(KtFakeSourceElementKind.DelegatingConstructorCall)
constructedTypeRef = delegatedSuperTypeRef.copyWithNewSourceKind(KtFakeSourceElementKind.ImplicitTypeRef)
isThis = false
@@ -945,6 +947,7 @@ open class RawFirBuilder(
ownerClassHasDefaultConstructor: Boolean
): FirDeclaration {
val ktEnumEntry = this@toFirEnumEntry
val containingClassIsExpectClass = hasExpectModifier() || this@RawFirBuilder.context.containerIsExpect
return buildEnumEntry {
source = toFirSourceElement()
moduleData = baseModuleData
@@ -953,7 +956,7 @@ open class RawFirBuilder(
name = nameAsSafeName
status = FirDeclarationStatusImpl(Visibilities.Public, Modality.FINAL).apply {
isStatic = true
isExpect = hasExpectModifier() || this@RawFirBuilder.context.containerIsExpect
isExpect = containingClassIsExpectClass
}
symbol = FirEnumEntrySymbol(callableIdForName(nameAsSafeName))
if (ownerClassHasDefaultConstructor && ktEnumEntry.initializerList == null &&
@@ -992,7 +995,8 @@ open class RawFirBuilder(
correctedEnumSelfTypeRef,
delegatedEntrySelfType,
owner = ktEnumEntry,
typeParameters
typeParameters,
containingClassIsExpectClass
)
// Use ANONYMOUS_OBJECT_NAME for the owner class id for enum entry declarations (see KT-42351)
withChildClassName(SpecialNames.ANONYMOUS, forceLocalContext = true, isExpect = false) {
@@ -2,7 +2,7 @@
// FILE: common.kt
expect enum class En(x: Int) {
<!NONE_APPLICABLE!>E1,<!>
E1,
E2(42),
;