[FIR] Check the presence of delegated constructor call via stubs
After `4b8b7aaa` external classes' secondary constructors should not have a delegated call, so we don't create a call if there's no explicit call. But we need to check if there is. The failing tests were muted in `8fcf91d8`, and are now unmuted back. Those are the ones in the `testData/rawBuilder/declarations` folder. These tests fail because they supply PSI stubs for the secondary constructors, so arbitrary operations (like reading .text of the delegated constructor call) are not allowed for them. This commit modifies secondary constructor stubs to include the required information. ^KT-65268 Fixed Merge-request: KT-MR-13982 Merged-by: Nikolay Lunyak <Nikolay.Lunyak@jetbrains.com>
This commit is contained in:
committed by
Space Team
parent
77dba281a3
commit
9688865953
+2
-4
@@ -2006,14 +2006,12 @@ open class PsiRawFirBuilder(
|
||||
}
|
||||
dispatchReceiverType = owner.obtainDispatchReceiverForConstructor()
|
||||
contextReceivers.addAll(convertContextReceivers(owner.contextReceivers))
|
||||
val delegationCall = getDelegationCall()
|
||||
val hasExplicitDelegationCall = delegationCall.textLength > 0
|
||||
if (!owner.hasModifier(EXTERNAL_KEYWORD) || hasExplicitDelegationCall) {
|
||||
if (!owner.hasModifier(EXTERNAL_KEYWORD) || isExplicitDelegationCall()) {
|
||||
delegatedConstructor = buildOrLazyDelegatedConstructorCall(
|
||||
isThis = isDelegatedCallToThis(),
|
||||
constructedTypeRef = delegatedTypeRef,
|
||||
) {
|
||||
delegationCall.convert(delegatedTypeRef)
|
||||
getDelegationCall().convert(delegatedTypeRef)
|
||||
}
|
||||
}
|
||||
this@PsiRawFirBuilder.context.firFunctionTargets += target
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_TREE_ACCESS: KT-65268
|
||||
@Target(
|
||||
AnnotationTarget.CLASS,
|
||||
AnnotationTarget.PROPERTY,
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_TREE_ACCESS: KT-65268
|
||||
open class A(init: A.() -> Unit) {
|
||||
val prop: String = ""
|
||||
}
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_TREE_ACCESS: KT-65268
|
||||
object A {
|
||||
constructor()
|
||||
init {}
|
||||
|
||||
Vendored
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_TREE_ACCESS: KT-65268
|
||||
class A {
|
||||
constructor(param: @Anno("parameter type $prop") List<@Anno("nested parameter type $prop") Collection<@Anno("nested nested parameter type $prop") String>> = @Anno("defaultValue $prop") fun(i: @Anno("anonymousFunction parameter type $prop") Int): @Anno("anonymousFunction return type $prop") Int {})
|
||||
}
|
||||
Vendored
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_TREE_ACCESS: KT-65268
|
||||
package util
|
||||
|
||||
class A {
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_TREE_ACCESS: KT-65268
|
||||
class C {
|
||||
constructor(x) {}
|
||||
}
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_TREE_ACCESS: KT-65268
|
||||
class NoPrimary {
|
||||
val x: String
|
||||
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_TREE_ACCESS: KT-65268
|
||||
package util
|
||||
|
||||
@Target(AnnotationTarget.TYPE)
|
||||
|
||||
@@ -64,6 +64,15 @@ abstract class KtConstructor<T : KtConstructor<T>> : KtDeclarationStub<KotlinCon
|
||||
}
|
||||
}
|
||||
|
||||
fun isExplicitDelegationCall(): Boolean {
|
||||
stub?.let { return it.isExplicitDelegationCall() }
|
||||
return when (this) {
|
||||
is KtPrimaryConstructor -> false
|
||||
is KtSecondaryConstructor -> getDelegationCallOrNull()?.isImplicit == false
|
||||
else -> throw IllegalStateException("Unknown constructor type: $this")
|
||||
}
|
||||
}
|
||||
|
||||
override fun hasBody(): Boolean {
|
||||
stub?.let { return it.hasBody() }
|
||||
return bodyExpression != null
|
||||
|
||||
@@ -12,12 +12,12 @@ object KotlinStubVersions {
|
||||
// Though only kotlin declarations (no code in the bodies) are stubbed, please do increase this version
|
||||
// if you are not 100% sure it can be avoided.
|
||||
// Increasing this version will lead to reindexing of all kotlin source files on the first IDE startup with the new version.
|
||||
const val SOURCE_STUB_VERSION = 158
|
||||
const val SOURCE_STUB_VERSION = 159
|
||||
|
||||
// Binary stub version should be increased if stub format (org.jetbrains.kotlin.psi.stubs.impl) is changed
|
||||
// or changes are made to the core stub building code (org.jetbrains.kotlin.idea.decompiler.stubBuilder).
|
||||
// Increasing this version will lead to reindexing of all binary files that are potentially kotlin binaries (including all class files).
|
||||
private const val BINARY_STUB_VERSION = 96
|
||||
private const val BINARY_STUB_VERSION = 97
|
||||
|
||||
// Classfile stub version should be increased if changes are made to classfile stub building subsystem (org.jetbrains.kotlin.idea.decompiler.classFile)
|
||||
// Increasing this version will lead to reindexing of all classfiles.
|
||||
|
||||
@@ -91,6 +91,7 @@ interface KotlinConstructorStub<T : KtConstructor<T>> :
|
||||
KotlinCallableStubBase<T> {
|
||||
fun hasBody(): Boolean
|
||||
fun isDelegatedCallToThis(): Boolean
|
||||
fun isExplicitDelegationCall(): Boolean
|
||||
}
|
||||
|
||||
interface KotlinImportAliasStub : StubElement<KtImportAlias> {
|
||||
|
||||
+8
-3
@@ -12,7 +12,6 @@ import com.intellij.util.io.StringRef
|
||||
import org.jetbrains.annotations.NonNls
|
||||
import org.jetbrains.kotlin.psi.KtConstructor
|
||||
import org.jetbrains.kotlin.psi.stubs.KotlinConstructorStub
|
||||
import org.jetbrains.kotlin.psi.stubs.elements.StubIndexService.Companion.getInstance
|
||||
import java.io.IOException
|
||||
|
||||
abstract class KtConstructorElementType<T : KtConstructor<T>>(
|
||||
@@ -25,14 +24,18 @@ abstract class KtConstructorElementType<T : KtConstructor<T>>(
|
||||
nameRef: StringRef?,
|
||||
hasBody: Boolean,
|
||||
isDelegatedCallToThis: Boolean,
|
||||
isExplicitDelegationCall: Boolean,
|
||||
): KotlinConstructorStub<T>
|
||||
|
||||
protected abstract fun isDelegatedCallToThis(constructor: T): Boolean
|
||||
|
||||
protected abstract fun isExplicitDelegationCall(constructor: T): Boolean
|
||||
|
||||
override fun createStub(psi: T, parentStub: StubElement<*>): KotlinConstructorStub<T> {
|
||||
val hasBody = psi.hasBody()
|
||||
val isDelegatedCallToThis = isDelegatedCallToThis(psi)
|
||||
return newStub(parentStub, StringRef.fromString(psi.name), hasBody, isDelegatedCallToThis)
|
||||
val isExplicitDelegationCall = isExplicitDelegationCall(psi)
|
||||
return newStub(parentStub, StringRef.fromString(psi.name), hasBody, isDelegatedCallToThis, isExplicitDelegationCall)
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
@@ -40,6 +43,7 @@ abstract class KtConstructorElementType<T : KtConstructor<T>>(
|
||||
dataStream.writeName(stub.name)
|
||||
dataStream.writeBoolean(stub.hasBody())
|
||||
dataStream.writeBoolean(stub.isDelegatedCallToThis())
|
||||
dataStream.writeBoolean(stub.isExplicitDelegationCall())
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
@@ -47,7 +51,8 @@ abstract class KtConstructorElementType<T : KtConstructor<T>>(
|
||||
val name = dataStream.readName()
|
||||
val hasBody = dataStream.readBoolean()
|
||||
val isDelegatedCallToThis = dataStream.readBoolean()
|
||||
return newStub(parentStub, name, hasBody, isDelegatedCallToThis)
|
||||
val isExplicitDelegationCall = dataStream.readBoolean()
|
||||
return newStub(parentStub, name, hasBody, isDelegatedCallToThis, isExplicitDelegationCall)
|
||||
}
|
||||
|
||||
override fun indexStub(stub: KotlinConstructorStub<T>, sink: IndexSink) {
|
||||
|
||||
+4
-1
@@ -17,11 +17,14 @@ class KtPrimaryConstructorElementType(debugName: String) :
|
||||
nameRef: StringRef?,
|
||||
hasBody: Boolean,
|
||||
isDelegatedCallToThis: Boolean,
|
||||
isExplicitDelegationCall: Boolean,
|
||||
): KotlinConstructorStub<KtPrimaryConstructor> {
|
||||
return KotlinConstructorStubImpl(
|
||||
parentStub, KtStubElementTypes.PRIMARY_CONSTRUCTOR, nameRef, hasBody, isDelegatedCallToThis
|
||||
parentStub, KtStubElementTypes.PRIMARY_CONSTRUCTOR, nameRef, hasBody, isDelegatedCallToThis, isExplicitDelegationCall
|
||||
)
|
||||
}
|
||||
|
||||
override fun isDelegatedCallToThis(constructor: KtPrimaryConstructor) = false
|
||||
|
||||
override fun isExplicitDelegationCall(constructor: KtPrimaryConstructor) = false
|
||||
}
|
||||
+4
-1
@@ -17,11 +17,14 @@ class KtSecondaryConstructorElementType(debugName: String) :
|
||||
nameRef: StringRef?,
|
||||
hasBody: Boolean,
|
||||
isDelegatedCallToThis: Boolean,
|
||||
isExplicitDelegationCall: Boolean,
|
||||
): KotlinConstructorStub<KtSecondaryConstructor> {
|
||||
return KotlinConstructorStubImpl(
|
||||
parentStub, KtStubElementTypes.SECONDARY_CONSTRUCTOR, nameRef, hasBody, isDelegatedCallToThis
|
||||
parentStub, KtStubElementTypes.SECONDARY_CONSTRUCTOR, nameRef, hasBody, isDelegatedCallToThis, isExplicitDelegationCall
|
||||
)
|
||||
}
|
||||
|
||||
override fun isDelegatedCallToThis(constructor: KtSecondaryConstructor) = constructor.getDelegationCallOrNull()?.isCallToThis ?: true
|
||||
|
||||
override fun isExplicitDelegationCall(constructor: KtSecondaryConstructor) = constructor.getDelegationCallOrNull()?.isImplicit == false
|
||||
}
|
||||
@@ -18,6 +18,7 @@ class KotlinConstructorStubImpl<T : KtConstructor<T>>(
|
||||
private val containingClassName: StringRef?,
|
||||
private val hasBody: Boolean,
|
||||
private val isDelegatedCallToThis: Boolean,
|
||||
private val isExplicitDelegationCall: Boolean,
|
||||
) : KotlinStubBaseImpl<T>(parent, elementType), KotlinConstructorStub<T> {
|
||||
override fun getFqName() = null
|
||||
override fun getName() = StringRef.toString(containingClassName)
|
||||
@@ -25,4 +26,5 @@ class KotlinConstructorStubImpl<T : KtConstructor<T>>(
|
||||
override fun isExtension() = false
|
||||
override fun hasBody() = hasBody
|
||||
override fun isDelegatedCallToThis() = isDelegatedCallToThis
|
||||
override fun isExplicitDelegationCall() = isExplicitDelegationCall
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user