Support inline classes in MPP resolver/checker model

This commit is contained in:
Mikhail Zarechenskiy
2018-06-08 15:30:27 +03:00
parent 3d57276bc6
commit 8148bdc4d0
14 changed files with 235 additions and 15 deletions
@@ -265,7 +265,10 @@ class DeclarationsChecker(
trace.report(EXPECTED_ENUM_CONSTRUCTOR.on(declaration))
}
if (declaration is KtPrimaryConstructor && !DescriptorUtils.isAnnotationClass(constructorDescriptor.constructedClass)) {
if (declaration is KtPrimaryConstructor &&
!DescriptorUtils.isAnnotationClass(constructorDescriptor.constructedClass) &&
!constructorDescriptor.constructedClass.isInline
) {
for (parameter in declaration.valueParameters) {
if (parameter.hasValOrVar()) {
trace.report(EXPECTED_CLASS_CONSTRUCTOR_PROPERTY_PARAMETER.on(parameter))
@@ -26,11 +26,9 @@ import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.hasActualModifier
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.resolve.descriptorUtil.isAnnotationConstructor
import org.jetbrains.kotlin.resolve.descriptorUtil.isPrimaryConstructorOfInlineClass
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver.Compatibility
@@ -137,9 +135,7 @@ object ExpectedActualDeclarationChecker : DeclarationChecker {
if (compatibility.allStrongIncompatibilities()) return
if (Compatible in compatibility) {
// we suppress error, because annotation classes can only have one constructor and it's a 100% boilerplate
// to require every annotation constructor with additional parameters with default values be marked with the `actual` modifier
if (checkActual && !descriptor.isAnnotationConstructor()) {
if (checkActual && requireActualModifier(descriptor, trace)) {
trace.report(Errors.ACTUAL_MISSING.on(reportOn))
}
@@ -204,6 +200,22 @@ object ExpectedActualDeclarationChecker : DeclarationChecker {
}
}
// we don't require `actual` modifier on
// - annotation constructors, because annotation classes can only have one constructor
// - inline class primary constructors, because inline class must have primary constructor
// - value parameter inside primary constructor of inline class, because inline class must have one value parameter
private fun requireActualModifier(descriptor: MemberDescriptor, trace: BindingTrace): Boolean {
return !descriptor.isAnnotationConstructor() &&
!descriptor.isPrimaryConstructorOfInlineClass() &&
!isMainPropertyOfInlineClass(descriptor, trace)
}
private fun isMainPropertyOfInlineClass(descriptor: MemberDescriptor, trace: BindingTrace): Boolean {
if (descriptor !is PropertyDescriptor) return false
if (!descriptor.containingDeclaration.isInlineClass()) return false
return trace.bindingContext[BindingContext.BACKING_FIELD_REQUIRED, descriptor] == true
}
// This should ideally be handled by CallableMemberDescriptor.Kind, but default constructors have kind DECLARATION and non-empty source.
// Their source is the containing KtClass instance though, as opposed to explicit constructors, whose source is KtConstructor
private fun MemberDescriptor.isExplicitActualDeclaration(): Boolean =