[FE] Prohibit default arguments in expect declarations actualized via typealias
Cases when default argument inhertied from super class are allowed. Some tests for default arguments already exist and can be found in `testData/diagnostics/tests/multiplatform/defaultArguments`, for example `annotationsViaActualTypeAlias.kt`. ^KT-57614 Fixed Merge-request: KT-MR-10356 Merged-by: Roman Efremov <Roman.Efremov@jetbrains.com>
This commit is contained in:
committed by
Space Team
parent
9829a2bf98
commit
d2eb4a0abf
@@ -800,6 +800,7 @@ public interface Errors {
|
||||
DiagnosticFactory0<KtTypeAlias> ACTUAL_TYPE_ALIAS_WITH_USE_SITE_VARIANCE = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);
|
||||
DiagnosticFactory0<KtTypeAlias> ACTUAL_TYPE_ALIAS_WITH_COMPLEX_SUBSTITUTION = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);
|
||||
DiagnosticFactory0<PsiElement> ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory2<KtNamedDeclaration, ClassDescriptor, Collection<FunctionDescriptor>> DEFAULT_ARGUMENTS_IN_EXPECT_WITH_ACTUAL_TYPEALIAS = DiagnosticFactory2.create(ERROR);
|
||||
DiagnosticFactory1<PsiElement, ValueParameterDescriptor> ACTUAL_ANNOTATION_CONFLICTING_DEFAULT_ARGUMENT_VALUE =
|
||||
DiagnosticFactory1.create(ERROR);
|
||||
|
||||
|
||||
+4
@@ -363,6 +363,10 @@ public class DefaultErrorMessages {
|
||||
MAP.put(ACTUAL_TYPE_ALIAS_WITH_COMPLEX_SUBSTITUTION, "Type arguments in the right-hand side of actual type alias should be its type parameters in the same order, e.g. 'actual typealias Foo<A, B> = Bar<A, B>'");
|
||||
MAP.put(ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS, "Actual function cannot have default argument values, they should be declared in the expected function");
|
||||
MAP.put(ACTUAL_ANNOTATION_CONFLICTING_DEFAULT_ARGUMENT_VALUE, "Parameter ''{0}'' has conflicting values in the expected and actual annotation", NAME);
|
||||
MAP.put(DEFAULT_ARGUMENTS_IN_EXPECT_WITH_ACTUAL_TYPEALIAS,
|
||||
"Default argument values inside expect declaration ''{0}'' are not allowed if it is actualized via typealias. " +
|
||||
"Possible fix is to remove default argument values in members:{1}",
|
||||
NAME, DESCRIPTORS_ON_NEWLINE_WITH_INDENT);
|
||||
|
||||
MAP.put(EXPECTED_FUNCTION_SOURCE_WITH_DEFAULT_ARGUMENTS_NOT_FOUND,
|
||||
"Expected function source is not found, therefore it's impossible to generate default argument values declared there. " +
|
||||
|
||||
@@ -50,8 +50,6 @@ import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||
import org.jetbrains.kotlin.utils.IDEAPlatforms
|
||||
import org.jetbrains.kotlin.utils.IDEAPluginsCompatibilityAPI
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||
import java.io.PrintWriter
|
||||
import java.io.StringWriter
|
||||
|
||||
object Renderers {
|
||||
|
||||
@@ -717,6 +715,20 @@ object Renderers {
|
||||
propertyAccessorRenderingPolicy = PropertyAccessorRenderingPolicy.PRETTY
|
||||
}.asRenderer()
|
||||
|
||||
@JvmField
|
||||
val DESCRIPTORS_ON_NEWLINE_WITH_INDENT = object : DiagnosticParameterRenderer<Collection<DeclarationDescriptor>> {
|
||||
private val mode = MultiplatformDiagnosticRenderingMode()
|
||||
|
||||
override fun render(obj: Collection<DeclarationDescriptor>, renderingContext: RenderingContext): String {
|
||||
return buildString {
|
||||
for (descriptor in obj) {
|
||||
mode.newLine(this)
|
||||
mode.renderDescriptor(this, descriptor, renderingContext, "")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun renderExpressionType(type: KotlinType?, dataFlowTypes: Set<KotlinType>?): String {
|
||||
if (type == null)
|
||||
return "Type is unknown"
|
||||
|
||||
+33
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.isPrimaryConstructorOfInlineC
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.*
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility.*
|
||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||
import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
|
||||
import org.jetbrains.kotlin.resolve.source.PsiSourceFile
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
@@ -203,6 +204,34 @@ class ExpectedActualDeclarationChecker(
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkIfExpectHasDefaultArgumentsAndActualizedWithTypealias(
|
||||
expectDescriptor: MemberDescriptor,
|
||||
actualDeclaration: KtNamedDeclaration,
|
||||
trace: BindingTrace,
|
||||
) {
|
||||
if (expectDescriptor !is ClassDescriptor ||
|
||||
actualDeclaration !is KtTypeAlias ||
|
||||
expectDescriptor.kind == ClassKind.ANNOTATION_CLASS
|
||||
) return
|
||||
|
||||
val members = expectDescriptor.constructors + expectDescriptor.unsubstitutedMemberScope
|
||||
.getContributedDescriptors(DescriptorKindFilter.FUNCTIONS)
|
||||
.filterIsInstance<FunctionDescriptor>()
|
||||
|
||||
val membersWithDefaultValueParameters = members
|
||||
.filter { it.valueParameters.any { p -> p.declaresDefaultValue() }}
|
||||
|
||||
if (membersWithDefaultValueParameters.isEmpty()) return
|
||||
|
||||
trace.report(
|
||||
Errors.DEFAULT_ARGUMENTS_IN_EXPECT_WITH_ACTUAL_TYPEALIAS.on(
|
||||
actualDeclaration,
|
||||
expectDescriptor,
|
||||
membersWithDefaultValueParameters
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private fun MemberDescriptor.hasNoActualWithDiagnostic(
|
||||
compatibility: Map<ExpectActualCompatibility<MemberDescriptor>, List<MemberDescriptor>>
|
||||
): Boolean {
|
||||
@@ -307,6 +336,10 @@ class ExpectedActualDeclarationChecker(
|
||||
}
|
||||
}
|
||||
}
|
||||
val expectSingleCandidate = compatibility.values.singleOrNull()?.firstOrNull()
|
||||
if (expectSingleCandidate != null) {
|
||||
checkIfExpectHasDefaultArgumentsAndActualizedWithTypealias(expectSingleCandidate, reportOn, trace)
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkAmbiguousExpects(
|
||||
|
||||
Reference in New Issue
Block a user