Fixed handling of default params in declaration (KT-23239)
This commit is contained in:
+34
-11
@@ -25,7 +25,6 @@ import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
|||||||
import org.jetbrains.kotlin.resolve.calls.model.CollectionLiteralKotlinCallArgument
|
import org.jetbrains.kotlin.resolve.calls.model.CollectionLiteralKotlinCallArgument
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallArgument
|
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallArgument
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.SimpleKotlinCallArgument
|
import org.jetbrains.kotlin.resolve.calls.model.SimpleKotlinCallArgument
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isAnnotationConstructor
|
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isParameterOfAnnotation
|
import org.jetbrains.kotlin.resolve.descriptorUtil.isParameterOfAnnotation
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver
|
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver
|
||||||
@@ -70,20 +69,44 @@ fun ValueParameterDescriptor.hasDefaultValue(): Boolean {
|
|||||||
return DFS.ifAny(
|
return DFS.ifAny(
|
||||||
listOf(this),
|
listOf(this),
|
||||||
{ current -> current.overriddenDescriptors.map(ValueParameterDescriptor::getOriginal) },
|
{ current -> current.overriddenDescriptors.map(ValueParameterDescriptor::getOriginal) },
|
||||||
{ it.declaresDefaultValue() || it.isActualParameterWithExpectedDefault }
|
{ it.declaresDefaultValue() || it.isActualParameterWithAnyExpectedDefault }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val ValueParameterDescriptor.isActualParameterWithExpectedDefault: Boolean
|
fun ValueParameterDescriptor.checkExpectedParameter(checker: (ValueParameterDescriptor) -> Boolean) : Boolean {
|
||||||
get() {
|
val function = containingDeclaration
|
||||||
val function = containingDeclaration
|
if (function is FunctionDescriptor && function.isActual) {
|
||||||
if (function is FunctionDescriptor && function.isActual) {
|
with(ExpectedActualResolver) {
|
||||||
with(ExpectedActualResolver) {
|
val expected = function.findCompatibleExpectedForActual(function.module).firstOrNull()
|
||||||
val expected = function.findCompatibleExpectedForActual(function.module).firstOrNull()
|
return expected is FunctionDescriptor && checker(expected.valueParameters[index])
|
||||||
return expected is FunctionDescriptor && expected.valueParameters[index].hasDefaultValue()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The following two properties describe two different situations:
|
||||||
|
*
|
||||||
|
* Consider hierarchy:
|
||||||
|
* expect open class A { foo(p = 1) }
|
||||||
|
* expect open class B : A { foo(p) }
|
||||||
|
*
|
||||||
|
* actual open class A { foo(p) }
|
||||||
|
* actual open class B : A { foo(p) }
|
||||||
|
*
|
||||||
|
* For parameter `p` of method `foo`:
|
||||||
|
* `Any` property returns `true` for both actual A and B
|
||||||
|
* `Corresponding` property returns `true` only for `actual A` because `expect B` declaration doesn't have an default value
|
||||||
|
*/
|
||||||
|
|
||||||
|
val ValueParameterDescriptor.isActualParameterWithAnyExpectedDefault: Boolean
|
||||||
|
get() {
|
||||||
|
return checkExpectedParameter { it.hasDefaultValue() }
|
||||||
|
}
|
||||||
|
|
||||||
|
val ValueParameterDescriptor.isActualParameterWithCorrespondingExpectedDefault: Boolean
|
||||||
|
get() {
|
||||||
|
return checkExpectedParameter { it.declaresDefaultValue() }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun KotlinCallArgument.isArrayAssignedAsNamedArgumentInAnnotation(
|
private fun KotlinCallArgument.isArrayAssignedAsNamedArgumentInAnnotation(
|
||||||
|
|||||||
+2
-2
@@ -24,7 +24,7 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils
|
|||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils.isEnumEntry
|
import org.jetbrains.kotlin.resolve.DescriptorUtils.isEnumEntry
|
||||||
import org.jetbrains.kotlin.resolve.MemberComparator
|
import org.jetbrains.kotlin.resolve.MemberComparator
|
||||||
import org.jetbrains.kotlin.resolve.RequireKotlinNames
|
import org.jetbrains.kotlin.resolve.RequireKotlinNames
|
||||||
import org.jetbrains.kotlin.resolve.calls.components.isActualParameterWithExpectedDefault
|
import org.jetbrains.kotlin.resolve.calls.components.isActualParameterWithAnyExpectedDefault
|
||||||
import org.jetbrains.kotlin.resolve.checkers.KotlinVersionStringAnnotationValueChecker
|
import org.jetbrains.kotlin.resolve.checkers.KotlinVersionStringAnnotationValueChecker
|
||||||
import org.jetbrains.kotlin.resolve.constants.EnumValue
|
import org.jetbrains.kotlin.resolve.constants.EnumValue
|
||||||
import org.jetbrains.kotlin.resolve.constants.IntValue
|
import org.jetbrains.kotlin.resolve.constants.IntValue
|
||||||
@@ -408,7 +408,7 @@ class DescriptorSerializer private constructor(
|
|||||||
private fun valueParameter(descriptor: ValueParameterDescriptor): ProtoBuf.ValueParameter.Builder {
|
private fun valueParameter(descriptor: ValueParameterDescriptor): ProtoBuf.ValueParameter.Builder {
|
||||||
val builder = ProtoBuf.ValueParameter.newBuilder()
|
val builder = ProtoBuf.ValueParameter.newBuilder()
|
||||||
|
|
||||||
val declaresDefaultValue = descriptor.declaresDefaultValue() || descriptor.isActualParameterWithExpectedDefault
|
val declaresDefaultValue = descriptor.declaresDefaultValue() || descriptor.isActualParameterWithAnyExpectedDefault
|
||||||
|
|
||||||
val flags = Flags.getValueParameterFlags(
|
val flags = Flags.getValueParameterFlags(
|
||||||
hasAnnotations(descriptor), declaresDefaultValue, descriptor.isCrossinline, descriptor.isNoinline
|
hasAnnotations(descriptor), declaresDefaultValue, descriptor.isCrossinline, descriptor.isNoinline
|
||||||
|
|||||||
+8
-3
@@ -28,7 +28,8 @@ import org.jetbrains.kotlin.js.translate.utils.BindingUtils.getClassDescriptor
|
|||||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.pureFqn
|
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.pureFqn
|
||||||
import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.getSupertypesWithoutFakes
|
import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.getSupertypesWithoutFakes
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.hasOrInheritsParametersWithDefaultValue
|
import org.jetbrains.kotlin.resolve.calls.components.hasDefaultValue
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.components.isActualParameterWithCorrespondingExpectedDefault
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.hasOwnParametersWithDefaultValue
|
import org.jetbrains.kotlin.resolve.descriptorUtil.hasOwnParametersWithDefaultValue
|
||||||
|
|
||||||
class DeclarationBodyVisitor(
|
class DeclarationBodyVisitor(
|
||||||
@@ -110,8 +111,12 @@ class DeclarationBodyVisitor(
|
|||||||
initializerStatements.add(statement)
|
initializerStatements.add(statement)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun hasParametersWithDefaultValue(descriptor: FunctionDescriptor) = descriptor.valueParameters.any { it.hasDefaultValue() }
|
||||||
|
private fun hasCorrespondingExpectParametersWithDefaultValue(descriptor: FunctionDescriptor) =
|
||||||
|
descriptor.valueParameters.any { it.isActualParameterWithCorrespondingExpectedDefault }
|
||||||
|
|
||||||
override fun addFunction(descriptor: FunctionDescriptor, expression: JsExpression?, psi: KtElement?) {
|
override fun addFunction(descriptor: FunctionDescriptor, expression: JsExpression?, psi: KtElement?) {
|
||||||
if (!descriptor.hasOrInheritsParametersWithDefaultValue() || !descriptor.isOverridableOrOverrides) {
|
if (!hasParametersWithDefaultValue(descriptor) || !descriptor.isOverridableOrOverrides) {
|
||||||
if (expression != null) {
|
if (expression != null) {
|
||||||
context.addDeclarationStatement(context.addFunctionToPrototype(containingClass, descriptor, expression))
|
context.addDeclarationStatement(context.addFunctionToPrototype(containingClass, descriptor, expression))
|
||||||
}
|
}
|
||||||
@@ -125,7 +130,7 @@ class DeclarationBodyVisitor(
|
|||||||
context.addDeclarationStatement(JsAstUtils.assignment(functionRef, expression).makeStmt())
|
context.addDeclarationStatement(JsAstUtils.assignment(functionRef, expression).makeStmt())
|
||||||
}
|
}
|
||||||
|
|
||||||
if (descriptor.hasOwnParametersWithDefaultValue()) {
|
if (descriptor.hasOwnParametersWithDefaultValue() || hasCorrespondingExpectParametersWithDefaultValue(descriptor)) {
|
||||||
val caller = JsFunction(context.getScopeForDescriptor(containingClass), JsBlock(), "")
|
val caller = JsFunction(context.getScopeForDescriptor(containingClass), JsBlock(), "")
|
||||||
caller.source = psi?.finalElement
|
caller.source = psi?.finalElement
|
||||||
val callerContext = context
|
val callerContext = context
|
||||||
|
|||||||
Reference in New Issue
Block a user