[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
+10
@@ -3310,6 +3310,16 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.DEFAULT_ARGUMENTS_IN_EXPECT_WITH_ACTUAL_TYPEALIAS) { firDiagnostic ->
|
||||
DefaultArgumentsInExpectWithActualTypealiasImpl(
|
||||
firSymbolBuilder.classifierBuilder.buildClassLikeSymbol(firDiagnostic.a),
|
||||
firDiagnostic.b.map { firCallableSymbol ->
|
||||
firSymbolBuilder.callableBuilder.buildCallableSymbol(firCallableSymbol)
|
||||
},
|
||||
firDiagnostic as KtPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.ACTUAL_ANNOTATION_CONFLICTING_DEFAULT_ARGUMENT_VALUE) { firDiagnostic ->
|
||||
ActualAnnotationConflictingDefaultArgumentValueImpl(
|
||||
firSymbolBuilder.variableLikeBuilder.buildVariableLikeSymbol(firDiagnostic.a),
|
||||
|
||||
+6
@@ -2328,6 +2328,12 @@ sealed interface KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
||||
override val diagnosticClass get() = ActualFunctionWithDefaultArguments::class
|
||||
}
|
||||
|
||||
interface DefaultArgumentsInExpectWithActualTypealias : KtFirDiagnostic<KtTypeAlias> {
|
||||
override val diagnosticClass get() = DefaultArgumentsInExpectWithActualTypealias::class
|
||||
val expectClassSymbol: KtClassLikeSymbol
|
||||
val members: List<KtCallableSymbol>
|
||||
}
|
||||
|
||||
interface ActualAnnotationConflictingDefaultArgumentValue : KtFirDiagnostic<PsiElement> {
|
||||
override val diagnosticClass get() = ActualAnnotationConflictingDefaultArgumentValue::class
|
||||
val parameter: KtVariableLikeSymbol
|
||||
|
||||
+7
@@ -2808,6 +2808,13 @@ internal class ActualFunctionWithDefaultArgumentsImpl(
|
||||
token: KtLifetimeToken,
|
||||
) : KtAbstractFirDiagnostic<PsiElement>(firDiagnostic, token), KtFirDiagnostic.ActualFunctionWithDefaultArguments
|
||||
|
||||
internal class DefaultArgumentsInExpectWithActualTypealiasImpl(
|
||||
override val expectClassSymbol: KtClassLikeSymbol,
|
||||
override val members: List<KtCallableSymbol>,
|
||||
firDiagnostic: KtPsiDiagnostic,
|
||||
token: KtLifetimeToken,
|
||||
) : KtAbstractFirDiagnostic<KtTypeAlias>(firDiagnostic, token), KtFirDiagnostic.DefaultArgumentsInExpectWithActualTypealias
|
||||
|
||||
internal class ActualAnnotationConflictingDefaultArgumentValueImpl(
|
||||
override val parameter: KtVariableLikeSymbol,
|
||||
firDiagnostic: KtPsiDiagnostic,
|
||||
|
||||
+12
@@ -208,6 +208,12 @@ public class FirOldFrontendMPPDiagnosticsWithLightTreeTestGenerated extends Abst
|
||||
runTest("compiler/testData/diagnostics/tests/multiplatform/defaultArguments/constructor.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("constructorDefaultArgsViaActualTypealias.kt")
|
||||
public void testConstructorDefaultArgsViaActualTypealias() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/multiplatform/defaultArguments/constructorDefaultArgsViaActualTypealias.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("expectedDeclaresDefaultArguments.kt")
|
||||
public void testExpectedDeclaresDefaultArguments() throws Exception {
|
||||
@@ -225,6 +231,12 @@ public class FirOldFrontendMPPDiagnosticsWithLightTreeTestGenerated extends Abst
|
||||
public void testExpectedVsNonExpectedWithDefaults() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/multiplatform/defaultArguments/expectedVsNonExpectedWithDefaults.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("methodDefaultArgsViaActualTypealias.kt")
|
||||
public void testMethodDefaultArgsViaActualTypealias() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/multiplatform/defaultArguments/methodDefaultArgsViaActualTypealias.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
|
||||
+12
@@ -208,6 +208,12 @@ public class FirOldFrontendMPPDiagnosticsWithPsiTestGenerated extends AbstractFi
|
||||
runTest("compiler/testData/diagnostics/tests/multiplatform/defaultArguments/constructor.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("constructorDefaultArgsViaActualTypealias.kt")
|
||||
public void testConstructorDefaultArgsViaActualTypealias() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/multiplatform/defaultArguments/constructorDefaultArgsViaActualTypealias.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("expectedDeclaresDefaultArguments.kt")
|
||||
public void testExpectedDeclaresDefaultArguments() throws Exception {
|
||||
@@ -225,6 +231,12 @@ public class FirOldFrontendMPPDiagnosticsWithPsiTestGenerated extends AbstractFi
|
||||
public void testExpectedVsNonExpectedWithDefaults() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/multiplatform/defaultArguments/expectedVsNonExpectedWithDefaults.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("methodDefaultArgsViaActualTypealias.kt")
|
||||
public void testMethodDefaultArgsViaActualTypealias() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/multiplatform/defaultArguments/methodDefaultArgsViaActualTypealias.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
|
||||
+4
@@ -1117,6 +1117,10 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
||||
val ACTUAL_TYPE_ALIAS_WITH_USE_SITE_VARIANCE by error<KtTypeAlias>(PositioningStrategy.DECLARATION_SIGNATURE)
|
||||
val ACTUAL_TYPE_ALIAS_WITH_COMPLEX_SUBSTITUTION by error<KtTypeAlias>(PositioningStrategy.DECLARATION_SIGNATURE)
|
||||
val ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS by error<PsiElement>()
|
||||
val DEFAULT_ARGUMENTS_IN_EXPECT_WITH_ACTUAL_TYPEALIAS by error<KtTypeAlias> {
|
||||
parameter<FirClassSymbol<*>>("expectClassSymbol")
|
||||
parameter<Collection<FirCallableSymbol<*>>>("members")
|
||||
}
|
||||
val ACTUAL_ANNOTATION_CONFLICTING_DEFAULT_ARGUMENT_VALUE by error<PsiElement> {
|
||||
parameter<FirVariableSymbol<*>>("parameter")
|
||||
}
|
||||
|
||||
@@ -608,6 +608,7 @@ object FirErrors {
|
||||
val ACTUAL_TYPE_ALIAS_WITH_USE_SITE_VARIANCE by error0<KtTypeAlias>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
|
||||
val ACTUAL_TYPE_ALIAS_WITH_COMPLEX_SUBSTITUTION by error0<KtTypeAlias>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
|
||||
val ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS by error0<PsiElement>()
|
||||
val DEFAULT_ARGUMENTS_IN_EXPECT_WITH_ACTUAL_TYPEALIAS by error2<KtTypeAlias, FirClassSymbol<*>, Collection<FirCallableSymbol<*>>>()
|
||||
val ACTUAL_ANNOTATION_CONFLICTING_DEFAULT_ARGUMENT_VALUE by error1<PsiElement, FirVariableSymbol<*>>()
|
||||
val EXPECTED_FUNCTION_SOURCE_WITH_DEFAULT_ARGUMENTS_NOT_FOUND by error0<PsiElement>()
|
||||
val NO_ACTUAL_FOR_EXPECT by error3<KtNamedDeclaration, FirBasedSymbol<*>, FirModuleData, Map<ExpectActualCompatibility<FirBasedSymbol<*>>, Collection<FirBasedSymbol<*>>>>(SourceElementPositioningStrategies.INCOMPATIBLE_DECLARATION)
|
||||
|
||||
+40
-3
@@ -22,11 +22,12 @@ import org.jetbrains.kotlin.fir.declarations.utils.isExternal
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isTailRec
|
||||
import org.jetbrains.kotlin.fir.languageVersionSettings
|
||||
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||
import org.jetbrains.kotlin.fir.scopes.collectAllFunctions
|
||||
import org.jetbrains.kotlin.fir.scopes.getDeclaredConstructors
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.declaredMemberScope
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.types.coneType
|
||||
import org.jetbrains.kotlin.fir.types.toSymbol
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility
|
||||
@@ -179,6 +180,15 @@ object FirExpectActualDeclarationChecker : FirBasicDeclarationChecker() {
|
||||
}
|
||||
}
|
||||
}
|
||||
val expectedSingleCandidate = compatibilityToMembersMap.values.singleOrNull()?.firstOrNull()
|
||||
if (expectedSingleCandidate != null) {
|
||||
checkIfExpectHasDefaultArgumentsAndActualizedWithTypealias(
|
||||
expectedSingleCandidate,
|
||||
symbol,
|
||||
context,
|
||||
reporter,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
@@ -241,6 +251,33 @@ object FirExpectActualDeclarationChecker : FirBasicDeclarationChecker() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkIfExpectHasDefaultArgumentsAndActualizedWithTypealias(
|
||||
expectSymbol: FirBasedSymbol<*>,
|
||||
actualSymbol: FirBasedSymbol<*>,
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter,
|
||||
) {
|
||||
if (expectSymbol !is FirClassSymbol ||
|
||||
actualSymbol !is FirTypeAliasSymbol ||
|
||||
expectSymbol.classKind == ClassKind.ANNOTATION_CLASS
|
||||
) return
|
||||
|
||||
val membersWithDefaultValueParameters =
|
||||
expectSymbol.declaredMemberScope(expectSymbol.moduleData.session, memberRequiredPhase = null)
|
||||
.run { collectAllFunctions() + getDeclaredConstructors() }
|
||||
.filter { it.valueParameterSymbols.any(FirValueParameterSymbol::hasDefaultValue) }
|
||||
|
||||
if (membersWithDefaultValueParameters.isEmpty()) return
|
||||
|
||||
reporter.reportOn(
|
||||
actualSymbol.source,
|
||||
FirErrors.DEFAULT_ARGUMENTS_IN_EXPECT_WITH_ACTUAL_TYPEALIAS,
|
||||
expectSymbol,
|
||||
membersWithDefaultValueParameters,
|
||||
context
|
||||
)
|
||||
}
|
||||
|
||||
fun Map<out ExpectActualCompatibility<*>, *>.allStrongIncompatibilities(): Boolean {
|
||||
return keys.all { it is Incompatible && it.kind == IncompatibilityKind.STRONG }
|
||||
}
|
||||
|
||||
+13
@@ -45,6 +45,19 @@ object FirDiagnosticRenderers {
|
||||
|
||||
val SYMBOLS = KtDiagnosticRenderers.COLLECTION(SYMBOL)
|
||||
|
||||
val SYMBOLS_ON_NEWLINE_WITH_INDENT = object : ContextIndependentParameterRenderer<Collection<FirCallableSymbol<*>>> {
|
||||
private val mode = MultiplatformDiagnosticRenderingMode()
|
||||
|
||||
override fun render(obj: Collection<FirCallableSymbol<*>>): String {
|
||||
return buildString {
|
||||
for (symbol in obj) {
|
||||
mode.newLine(this)
|
||||
mode.renderSymbol(this, symbol, "")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val RENDER_COLLECTION_OF_TYPES = Renderer { types: Collection<ConeKotlinType> ->
|
||||
types.joinToString(separator = ", ") { type ->
|
||||
RENDER_TYPE.render(type)
|
||||
|
||||
+9
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.DECL
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.FIR
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.FQ_NAMES_IN_TYPES
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.FUNCTIONAL_TYPE_KINDS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.SYMBOLS_ON_NEWLINE_WITH_INDENT
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.MODULE_DATA
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.NAME_OF_CONTAINING_DECLARATION_OR_FILE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.RENDER_CLASS_OR_OBJECT
|
||||
@@ -148,6 +149,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DATA_CLASS_VARARG
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DATA_CLASS_WITHOUT_PARAMETERS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DATA_OBJECT_CUSTOM_EQUALS_OR_HASH_CODE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DECLARATION_CANT_BE_INLINED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DEFAULT_ARGUMENTS_IN_EXPECT_WITH_ACTUAL_TYPEALIAS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DEFINITELY_NON_NULLABLE_AS_REIFIED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DELEGATED_PROPERTY_INSIDE_VALUE_CLASS
|
||||
@@ -1792,6 +1794,13 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
|
||||
ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS,
|
||||
"Actual function cannot have default argument values, they should be declared in the expected function"
|
||||
)
|
||||
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}",
|
||||
DECLARATION_NAME,
|
||||
SYMBOLS_ON_NEWLINE_WITH_INDENT,
|
||||
)
|
||||
map.put(
|
||||
ACTUAL_ANNOTATION_CONFLICTING_DEFAULT_ARGUMENT_VALUE,
|
||||
"Parameter ''{0}'' has conflicting values in the expected and actual annotation",
|
||||
|
||||
-12
@@ -7457,18 +7457,6 @@ public class FirLightTreeBlackBoxCodegenTestGenerated extends AbstractFirLightTr
|
||||
runTest("compiler/testData/codegen/box/compileKotlinAgainstKotlin/enum.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("expectClassActualTypeAlias.kt")
|
||||
public void testExpectClassActualTypeAlias() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/compileKotlinAgainstKotlin/expectClassActualTypeAlias.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("expectClassActualTypeAlias2.kt")
|
||||
public void testExpectClassActualTypeAlias2() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/compileKotlinAgainstKotlin/expectClassActualTypeAlias2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("fakeOverridesForIntersectionTypes.kt")
|
||||
public void testFakeOverridesForIntersectionTypes() throws Exception {
|
||||
|
||||
-12
@@ -7457,18 +7457,6 @@ public class FirPsiBlackBoxCodegenTestGenerated extends AbstractFirPsiBlackBoxCo
|
||||
runTest("compiler/testData/codegen/box/compileKotlinAgainstKotlin/enum.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("expectClassActualTypeAlias.kt")
|
||||
public void testExpectClassActualTypeAlias() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/compileKotlinAgainstKotlin/expectClassActualTypeAlias.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("expectClassActualTypeAlias2.kt")
|
||||
public void testExpectClassActualTypeAlias2() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/compileKotlinAgainstKotlin/expectClassActualTypeAlias2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("fakeOverridesForIntersectionTypes.kt")
|
||||
public void testFakeOverridesForIntersectionTypes() throws Exception {
|
||||
|
||||
@@ -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(
|
||||
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
// IGNORE_BACKEND: NATIVE
|
||||
// !LANGUAGE: +MultiPlatformProjects
|
||||
// IGNORE_BACKEND_K2: JVM_IR, JS_IR, NATIVE
|
||||
// FIR status: In FIR, declaring the same `expect` and `actual` classes in one compiler module is not possible (see KT-55177).
|
||||
|
||||
// MODULE: lib
|
||||
// FILE: impl.kt
|
||||
class A(val result: String = "OK")
|
||||
|
||||
// MODULE: main(lib)
|
||||
// FILE: multiplatform.kt
|
||||
expect class B(result: String = "FAIL")
|
||||
|
||||
actual typealias B = A
|
||||
|
||||
fun box(): String {
|
||||
return B().result
|
||||
}
|
||||
-19
@@ -1,19 +0,0 @@
|
||||
// !LANGUAGE: +MultiPlatformProjects
|
||||
// IGNORE_BACKEND_K1: ANY
|
||||
// IGNORE_BACKEND_MULTI_MODULE: ANY
|
||||
|
||||
// MODULE: lib1
|
||||
// FILE: impl.kt
|
||||
class A(val result: String = "OK")
|
||||
|
||||
// MODULE: lib2
|
||||
// FILE: B.kt
|
||||
expect class B(result: String = "FAIL")
|
||||
|
||||
// MODULE: main(lib1)()(lib2)
|
||||
// FILE: multiplatform.kt
|
||||
actual typealias B = A
|
||||
|
||||
fun box(): String {
|
||||
return B().result
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
// FIR_IDENTICAL
|
||||
// MODULE: m1-common
|
||||
// FILE: common.kt
|
||||
expect class DefaultArgsInConstructor(p1: String = "common", p2: String = "common", p3: String)
|
||||
|
||||
// MODULE: m2-jvm()()(m1-common)
|
||||
// FILE: jvm.kt
|
||||
class DefaultArgsInConstructorImpl(p1: String = "common", p2: String = "common", p3: String)
|
||||
|
||||
<!DEFAULT_ARGUMENTS_IN_EXPECT_WITH_ACTUAL_TYPEALIAS!>actual typealias DefaultArgsInConstructor = DefaultArgsInConstructorImpl<!>
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
// FIR_IDENTICAL
|
||||
// !DIAGNOSTICS: -ACTUAL_WITHOUT_EXPECT
|
||||
// MODULE: m1-common
|
||||
// FILE: common.kt
|
||||
expect class A {
|
||||
fun foo(p1: String = "common", p2: String = "common", p3: String)
|
||||
}
|
||||
|
||||
expect class B {
|
||||
fun foo(s: String)
|
||||
}
|
||||
|
||||
interface I {
|
||||
fun methodWithDefaultArg(s: String = "common")
|
||||
}
|
||||
|
||||
expect class WithDefaultArgFromSuper : I {
|
||||
override fun methodWithDefaultArg(s: String)
|
||||
}
|
||||
|
||||
expect open class WithIncompatibility {
|
||||
fun foo(p: String = "common")
|
||||
}
|
||||
|
||||
// MODULE: m2-jvm()()(m1-common)
|
||||
// FILE: jvm.kt
|
||||
|
||||
class AImpl {
|
||||
fun foo(p1: String = "impl", p2: String = "impl", p3: String) {}
|
||||
}
|
||||
|
||||
<!DEFAULT_ARGUMENTS_IN_EXPECT_WITH_ACTUAL_TYPEALIAS!>actual typealias A = AImpl<!>
|
||||
|
||||
class BImpl {
|
||||
fun foo(s: String = "impl") {}
|
||||
}
|
||||
|
||||
actual typealias B = BImpl
|
||||
|
||||
class WithDefaultArgFromSuperImpl : I {
|
||||
override fun methodWithDefaultArg(s: String) {}
|
||||
}
|
||||
|
||||
actual typealias WithDefaultArgFromSuper = WithDefaultArgFromSuperImpl
|
||||
|
||||
class WithIncompatibilityImpl {
|
||||
fun foo(p: String) {}
|
||||
}
|
||||
|
||||
<!DEFAULT_ARGUMENTS_IN_EXPECT_WITH_ACTUAL_TYPEALIAS!>actual typealias WithIncompatibility = WithIncompatibilityImpl<!>
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
package test
|
||||
|
||||
expect class A(p: String = "constructor") {
|
||||
fun foo(p: String = "common")
|
||||
fun bar(p: String)
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package test
|
||||
|
||||
class AImpl(p: String) {
|
||||
fun foo(p: String) {}
|
||||
fun bar(p: String) {}
|
||||
}
|
||||
|
||||
actual typealias A = AImpl
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
-- Common --
|
||||
Exit code: OK
|
||||
Output:
|
||||
|
||||
-- JVM --
|
||||
Exit code: COMPILATION_ERROR
|
||||
Output:
|
||||
compiler/testData/multiplatform/defaultArguments/methodDefaultArgsViaTypealias/jvm.kt:8:1: error: default argument values inside expect declaration 'A' are not allowed if it is actualized via typealias. Possible fix is to remove default argument values in members:
|
||||
public constructor A(p: String = ...)
|
||||
|
||||
public final expect fun foo(p: String = ...): Unit
|
||||
|
||||
actual typealias A = AImpl
|
||||
^
|
||||
Generated
+12
@@ -22459,6 +22459,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
||||
runTest("compiler/testData/diagnostics/tests/multiplatform/defaultArguments/constructor.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("constructorDefaultArgsViaActualTypealias.kt")
|
||||
public void testConstructorDefaultArgsViaActualTypealias() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/multiplatform/defaultArguments/constructorDefaultArgsViaActualTypealias.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("expectedDeclaresDefaultArguments.kt")
|
||||
public void testExpectedDeclaresDefaultArguments() throws Exception {
|
||||
@@ -22476,6 +22482,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
||||
public void testExpectedVsNonExpectedWithDefaults() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/multiplatform/defaultArguments/expectedVsNonExpectedWithDefaults.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("methodDefaultArgsViaActualTypealias.kt")
|
||||
public void testMethodDefaultArgsViaActualTypealias() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/multiplatform/defaultArguments/methodDefaultArgsViaActualTypealias.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
|
||||
-12
@@ -7241,18 +7241,6 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/compileKotlinAgainstKotlin/enum.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("expectClassActualTypeAlias.kt")
|
||||
public void testExpectClassActualTypeAlias() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/compileKotlinAgainstKotlin/expectClassActualTypeAlias.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("expectClassActualTypeAlias2.kt")
|
||||
public void testExpectClassActualTypeAlias2() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/compileKotlinAgainstKotlin/expectClassActualTypeAlias2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("fakeOverridesForIntersectionTypes.kt")
|
||||
public void testFakeOverridesForIntersectionTypes() throws Exception {
|
||||
|
||||
-12
@@ -7457,18 +7457,6 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/compileKotlinAgainstKotlin/enum.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("expectClassActualTypeAlias.kt")
|
||||
public void testExpectClassActualTypeAlias() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/compileKotlinAgainstKotlin/expectClassActualTypeAlias.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("expectClassActualTypeAlias2.kt")
|
||||
public void testExpectClassActualTypeAlias2() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/compileKotlinAgainstKotlin/expectClassActualTypeAlias2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("fakeOverridesForIntersectionTypes.kt")
|
||||
public void testFakeOverridesForIntersectionTypes() throws Exception {
|
||||
|
||||
-12
@@ -7457,18 +7457,6 @@ public class IrBlackBoxCodegenWithIrInlinerTestGenerated extends AbstractIrBlack
|
||||
runTest("compiler/testData/codegen/box/compileKotlinAgainstKotlin/enum.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("expectClassActualTypeAlias.kt")
|
||||
public void testExpectClassActualTypeAlias() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/compileKotlinAgainstKotlin/expectClassActualTypeAlias.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("expectClassActualTypeAlias2.kt")
|
||||
public void testExpectClassActualTypeAlias2() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/compileKotlinAgainstKotlin/expectClassActualTypeAlias2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("fakeOverridesForIntersectionTypes.kt")
|
||||
public void testFakeOverridesForIntersectionTypes() throws Exception {
|
||||
|
||||
-12
@@ -151,18 +151,6 @@ public class JvmIrAgainstOldBoxTestGenerated extends AbstractJvmIrAgainstOldBoxT
|
||||
runTest("compiler/testData/codegen/box/compileKotlinAgainstKotlin/enum.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("expectClassActualTypeAlias.kt")
|
||||
public void testExpectClassActualTypeAlias() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/compileKotlinAgainstKotlin/expectClassActualTypeAlias.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("expectClassActualTypeAlias2.kt")
|
||||
public void testExpectClassActualTypeAlias2() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/compileKotlinAgainstKotlin/expectClassActualTypeAlias2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("fakeOverridesForIntersectionTypes.kt")
|
||||
public void testFakeOverridesForIntersectionTypes() throws Exception {
|
||||
|
||||
-12
@@ -151,18 +151,6 @@ public class JvmOldAgainstIrBoxTestGenerated extends AbstractJvmOldAgainstIrBoxT
|
||||
runTest("compiler/testData/codegen/box/compileKotlinAgainstKotlin/enum.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("expectClassActualTypeAlias.kt")
|
||||
public void testExpectClassActualTypeAlias() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/compileKotlinAgainstKotlin/expectClassActualTypeAlias.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("expectClassActualTypeAlias2.kt")
|
||||
public void testExpectClassActualTypeAlias2() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/compileKotlinAgainstKotlin/expectClassActualTypeAlias2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("fakeOverridesForIntersectionTypes.kt")
|
||||
public void testFakeOverridesForIntersectionTypes() throws Exception {
|
||||
|
||||
Generated
+18
@@ -365,11 +365,29 @@ public class MultiPlatformIntegrationTestGenerated extends AbstractMultiPlatform
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/multiplatform/defaultArguments"), Pattern.compile("^([^\\.]+)$"), null, true);
|
||||
}
|
||||
|
||||
@TestMetadata("methodDefaultArgsViaTypealias")
|
||||
public void testMethodDefaultArgsViaTypealias() throws Exception {
|
||||
runTest("compiler/testData/multiplatform/defaultArguments/methodDefaultArgsViaTypealias/");
|
||||
}
|
||||
|
||||
@TestMetadata("useDefaultArgumentsInDependency")
|
||||
public void testUseDefaultArgumentsInDependency() throws Exception {
|
||||
runTest("compiler/testData/multiplatform/defaultArguments/useDefaultArgumentsInDependency/");
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/multiplatform/defaultArguments/methodDefaultArgsViaTypealias")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class MethodDefaultArgsViaTypealias extends AbstractMultiPlatformIntegrationTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInMethodDefaultArgsViaTypealias() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/multiplatform/defaultArguments/methodDefaultArgsViaTypealias"), Pattern.compile("^([^\\.]+)$"), null, true);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/multiplatform/defaultArguments/useDefaultArgumentsInDependency")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
-12
@@ -5689,18 +5689,6 @@ public class FirNativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTe
|
||||
runTest("compiler/testData/codegen/box/compileKotlinAgainstKotlin/enum.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("expectClassActualTypeAlias.kt")
|
||||
public void testExpectClassActualTypeAlias() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/compileKotlinAgainstKotlin/expectClassActualTypeAlias.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("expectClassActualTypeAlias2.kt")
|
||||
public void testExpectClassActualTypeAlias2() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/compileKotlinAgainstKotlin/expectClassActualTypeAlias2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("genericSetter.kt")
|
||||
public void testGenericSetter() throws Exception {
|
||||
|
||||
-12
@@ -5809,18 +5809,6 @@ public class FirNativeCodegenBoxTestNoPLGenerated extends AbstractNativeCodegenB
|
||||
runTest("compiler/testData/codegen/box/compileKotlinAgainstKotlin/enum.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("expectClassActualTypeAlias.kt")
|
||||
public void testExpectClassActualTypeAlias() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/compileKotlinAgainstKotlin/expectClassActualTypeAlias.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("expectClassActualTypeAlias2.kt")
|
||||
public void testExpectClassActualTypeAlias2() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/compileKotlinAgainstKotlin/expectClassActualTypeAlias2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("genericSetter.kt")
|
||||
public void testGenericSetter() throws Exception {
|
||||
|
||||
-12
@@ -5630,18 +5630,6 @@ public class NativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTest
|
||||
runTest("compiler/testData/codegen/box/compileKotlinAgainstKotlin/enum.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("expectClassActualTypeAlias.kt")
|
||||
public void testExpectClassActualTypeAlias() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/compileKotlinAgainstKotlin/expectClassActualTypeAlias.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("expectClassActualTypeAlias2.kt")
|
||||
public void testExpectClassActualTypeAlias2() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/compileKotlinAgainstKotlin/expectClassActualTypeAlias2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("genericSetter.kt")
|
||||
public void testGenericSetter() throws Exception {
|
||||
|
||||
-12
@@ -5690,18 +5690,6 @@ public class NativeCodegenBoxTestNoPLGenerated extends AbstractNativeCodegenBoxT
|
||||
runTest("compiler/testData/codegen/box/compileKotlinAgainstKotlin/enum.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("expectClassActualTypeAlias.kt")
|
||||
public void testExpectClassActualTypeAlias() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/compileKotlinAgainstKotlin/expectClassActualTypeAlias.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("expectClassActualTypeAlias2.kt")
|
||||
public void testExpectClassActualTypeAlias2() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/compileKotlinAgainstKotlin/expectClassActualTypeAlias2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("genericSetter.kt")
|
||||
public void testGenericSetter() throws Exception {
|
||||
|
||||
Reference in New Issue
Block a user