Move ExpectActualCompatibility to :compiler:resolution.common
This commit is contained in:
committed by
teamcityserver
parent
950db81aa4
commit
6e83820f97
@@ -29,7 +29,7 @@ import org.jetbrains.kotlin.resolve.VarianceConflictDiagnosticData;
|
|||||||
import org.jetbrains.kotlin.resolve.calls.inference.InferenceErrorData;
|
import org.jetbrains.kotlin.resolve.calls.inference.InferenceErrorData;
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||||
import org.jetbrains.kotlin.resolve.calls.tower.WrongResolutionToClassifier;
|
import org.jetbrains.kotlin.resolve.calls.tower.WrongResolutionToClassifier;
|
||||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver.Compatibility.Incompatible;
|
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility.Incompatible;
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.IncompatibleVersionErrorData;
|
import org.jetbrains.kotlin.serialization.deserialization.IncompatibleVersionErrorData;
|
||||||
import org.jetbrains.kotlin.types.KotlinType;
|
import org.jetbrains.kotlin.types.KotlinType;
|
||||||
|
|
||||||
@@ -704,10 +704,10 @@ public interface Errors {
|
|||||||
DiagnosticFactory0<PsiElement> EXPECTED_FUNCTION_SOURCE_WITH_DEFAULT_ARGUMENTS_NOT_FOUND = DiagnosticFactory0.create(ERROR);
|
DiagnosticFactory0<PsiElement> EXPECTED_FUNCTION_SOURCE_WITH_DEFAULT_ARGUMENTS_NOT_FOUND = DiagnosticFactory0.create(ERROR);
|
||||||
|
|
||||||
DiagnosticFactory3<KtNamedDeclaration, MemberDescriptor, ModuleDescriptor,
|
DiagnosticFactory3<KtNamedDeclaration, MemberDescriptor, ModuleDescriptor,
|
||||||
Map<Incompatible, Collection<MemberDescriptor>>> NO_ACTUAL_FOR_EXPECT =
|
Map<Incompatible<MemberDescriptor>, Collection<MemberDescriptor>>> NO_ACTUAL_FOR_EXPECT =
|
||||||
DiagnosticFactory3.create(ERROR, INCOMPATIBLE_DECLARATION);
|
DiagnosticFactory3.create(ERROR, INCOMPATIBLE_DECLARATION);
|
||||||
DiagnosticFactory2<KtNamedDeclaration, MemberDescriptor,
|
DiagnosticFactory2<KtNamedDeclaration, MemberDescriptor,
|
||||||
Map<Incompatible, Collection<MemberDescriptor>>> ACTUAL_WITHOUT_EXPECT =
|
Map<Incompatible<MemberDescriptor>, Collection<MemberDescriptor>>> ACTUAL_WITHOUT_EXPECT =
|
||||||
DiagnosticFactory2.create(ERROR, INCOMPATIBLE_DECLARATION);
|
DiagnosticFactory2.create(ERROR, INCOMPATIBLE_DECLARATION);
|
||||||
DiagnosticFactory2<KtNamedDeclaration, DeclarationDescriptor, Collection<ModuleDescriptor>> AMBIGUOUS_ACTUALS =
|
DiagnosticFactory2<KtNamedDeclaration, DeclarationDescriptor, Collection<ModuleDescriptor>> AMBIGUOUS_ACTUALS =
|
||||||
DiagnosticFactory2.create(ERROR, INCOMPATIBLE_DECLARATION);
|
DiagnosticFactory2.create(ERROR, INCOMPATIBLE_DECLARATION);
|
||||||
@@ -715,7 +715,7 @@ public interface Errors {
|
|||||||
DiagnosticFactory2.create(ERROR, INCOMPATIBLE_DECLARATION);
|
DiagnosticFactory2.create(ERROR, INCOMPATIBLE_DECLARATION);
|
||||||
|
|
||||||
DiagnosticFactory2<KtNamedDeclaration, ClassDescriptor,
|
DiagnosticFactory2<KtNamedDeclaration, ClassDescriptor,
|
||||||
List<Pair<MemberDescriptor, Map<Incompatible, Collection<MemberDescriptor>>>>> NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS =
|
List<Pair<MemberDescriptor, Map<Incompatible<MemberDescriptor>, Collection<MemberDescriptor>>>>> NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS =
|
||||||
DiagnosticFactory2.create(ERROR, ACTUAL_DECLARATION_NAME);
|
DiagnosticFactory2.create(ERROR, ACTUAL_DECLARATION_NAME);
|
||||||
DiagnosticFactory0<KtNamedDeclaration> ACTUAL_MISSING = DiagnosticFactory0.create(ERROR, ACTUAL_DECLARATION_NAME);
|
DiagnosticFactory0<KtNamedDeclaration> ACTUAL_MISSING = DiagnosticFactory0.create(ERROR, ACTUAL_DECLARATION_NAME);
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import com.intellij.psi.impl.source.tree.LeafPsiElement
|
|||||||
import com.intellij.psi.tree.TokenSet
|
import com.intellij.psi.tree.TokenSet
|
||||||
import org.jetbrains.kotlin.KtNodeTypes
|
import org.jetbrains.kotlin.KtNodeTypes
|
||||||
import org.jetbrains.kotlin.cfg.UnreachableCode
|
import org.jetbrains.kotlin.cfg.UnreachableCode
|
||||||
|
import org.jetbrains.kotlin.descriptors.MemberDescriptor
|
||||||
import org.jetbrains.kotlin.diagnostics.Errors.ACTUAL_WITHOUT_EXPECT
|
import org.jetbrains.kotlin.diagnostics.Errors.ACTUAL_WITHOUT_EXPECT
|
||||||
import org.jetbrains.kotlin.diagnostics.Errors.NO_ACTUAL_FOR_EXPECT
|
import org.jetbrains.kotlin.diagnostics.Errors.NO_ACTUAL_FOR_EXPECT
|
||||||
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
||||||
@@ -19,8 +20,8 @@ import org.jetbrains.kotlin.lexer.KtTokens.MODALITY_MODIFIERS
|
|||||||
import org.jetbrains.kotlin.lexer.KtTokens.VISIBILITY_MODIFIERS
|
import org.jetbrains.kotlin.lexer.KtTokens.VISIBILITY_MODIFIERS
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.*
|
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver.Compatibility.Incompatible
|
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility.Incompatible
|
||||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver.Compatibility.Incompatible.*
|
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility.Incompatible.*
|
||||||
import org.jetbrains.kotlin.utils.sure
|
import org.jetbrains.kotlin.utils.sure
|
||||||
|
|
||||||
object PositioningStrategies {
|
object PositioningStrategies {
|
||||||
@@ -114,7 +115,7 @@ object PositioningStrategies {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val ParametrizedDiagnostic<out KtNamedDeclaration>.firstIncompatibility: Incompatible?
|
private val ParametrizedDiagnostic<out KtNamedDeclaration>.firstIncompatibility: Incompatible<MemberDescriptor>?
|
||||||
get() {
|
get() {
|
||||||
val map = when (factory) {
|
val map = when (factory) {
|
||||||
NO_ACTUAL_FOR_EXPECT ->
|
NO_ACTUAL_FOR_EXPECT ->
|
||||||
|
|||||||
+16
-6
@@ -11,20 +11,21 @@ import kotlin.collections.CollectionsKt;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.config.LanguageVersion;
|
import org.jetbrains.kotlin.config.LanguageVersion;
|
||||||
|
import org.jetbrains.kotlin.descriptors.MemberDescriptor;
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory;
|
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory;
|
||||||
import org.jetbrains.kotlin.diagnostics.Errors;
|
import org.jetbrains.kotlin.diagnostics.Errors;
|
||||||
import org.jetbrains.kotlin.diagnostics.UnboundDiagnostic;
|
import org.jetbrains.kotlin.diagnostics.UnboundDiagnostic;
|
||||||
import org.jetbrains.kotlin.metadata.deserialization.VersionRequirement;
|
import org.jetbrains.kotlin.metadata.deserialization.VersionRequirement;
|
||||||
import org.jetbrains.kotlin.resolve.VarianceConflictDiagnosticData;
|
import org.jetbrains.kotlin.resolve.VarianceConflictDiagnosticData;
|
||||||
|
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility;
|
||||||
|
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility.Incompatible;
|
||||||
import org.jetbrains.kotlin.types.KotlinTypeKt;
|
import org.jetbrains.kotlin.types.KotlinTypeKt;
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions;
|
import org.jetbrains.kotlin.util.OperatorNameConventions;
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.AddToStdlibKt;
|
import org.jetbrains.kotlin.utils.addToStdlib.AddToStdlibKt;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.util.Collections;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
import java.util.ServiceLoader;
|
|
||||||
|
|
||||||
import static org.jetbrains.kotlin.diagnostics.Errors.*;
|
import static org.jetbrains.kotlin.diagnostics.Errors.*;
|
||||||
import static org.jetbrains.kotlin.diagnostics.rendering.Renderers.*;
|
import static org.jetbrains.kotlin.diagnostics.rendering.Renderers.*;
|
||||||
@@ -307,16 +308,16 @@ public class DefaultErrorMessages {
|
|||||||
"Please add the corresponding file to compilation sources");
|
"Please add the corresponding file to compilation sources");
|
||||||
|
|
||||||
MAP.put(NO_ACTUAL_FOR_EXPECT, "Expected {0} has no actual declaration in module {1}{2}", DECLARATION_NAME_WITH_KIND,
|
MAP.put(NO_ACTUAL_FOR_EXPECT, "Expected {0} has no actual declaration in module {1}{2}", DECLARATION_NAME_WITH_KIND,
|
||||||
MODULE_WITH_PLATFORM, PlatformIncompatibilityDiagnosticRenderer.TEXT);
|
MODULE_WITH_PLATFORM, adaptGenerics1(PlatformIncompatibilityDiagnosticRenderer.TEXT));
|
||||||
MAP.put(ACTUAL_WITHOUT_EXPECT, "{0} has no corresponding expected declaration{1}", CAPITALIZED_DECLARATION_NAME_WITH_KIND_AND_PLATFORM,
|
MAP.put(ACTUAL_WITHOUT_EXPECT, "{0} has no corresponding expected declaration{1}", CAPITALIZED_DECLARATION_NAME_WITH_KIND_AND_PLATFORM,
|
||||||
PlatformIncompatibilityDiagnosticRenderer.TEXT);
|
adaptGenerics1(PlatformIncompatibilityDiagnosticRenderer.TEXT));
|
||||||
MAP.put(AMBIGUOUS_ACTUALS, "{0} has several compatible actual declarations in modules {1}", CAPITALIZED_DECLARATION_NAME_WITH_KIND_AND_PLATFORM, commaSeparated(
|
MAP.put(AMBIGUOUS_ACTUALS, "{0} has several compatible actual declarations in modules {1}", CAPITALIZED_DECLARATION_NAME_WITH_KIND_AND_PLATFORM, commaSeparated(
|
||||||
MODULE));
|
MODULE));
|
||||||
MAP.put(AMBIGUOUS_EXPECTS, "{0} has several compatible expect declarations in modules {1}", CAPITALIZED_DECLARATION_NAME_WITH_KIND_AND_PLATFORM, commaSeparated(
|
MAP.put(AMBIGUOUS_EXPECTS, "{0} has several compatible expect declarations in modules {1}", CAPITALIZED_DECLARATION_NAME_WITH_KIND_AND_PLATFORM, commaSeparated(
|
||||||
MODULE));
|
MODULE));
|
||||||
|
|
||||||
MAP.put(NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS, "Actual class ''{0}'' has no corresponding members for expected class members:{1}",
|
MAP.put(NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS, "Actual class ''{0}'' has no corresponding members for expected class members:{1}",
|
||||||
NAME, IncompatibleExpectedActualClassScopesRenderer.TEXT);
|
NAME, adaptGenerics2(IncompatibleExpectedActualClassScopesRenderer.TEXT));
|
||||||
MAP.put(ACTUAL_MISSING, "Declaration must be marked with 'actual'");
|
MAP.put(ACTUAL_MISSING, "Declaration must be marked with 'actual'");
|
||||||
|
|
||||||
MAP.put(OPTIONAL_EXPECTATION_NOT_ON_EXPECTED, "'@OptionalExpectation' can only be used on an expected annotation class");
|
MAP.put(OPTIONAL_EXPECTATION_NOT_ON_EXPECTED, "'@OptionalExpectation' can only be used on an expected annotation class");
|
||||||
@@ -1100,6 +1101,15 @@ public class DefaultErrorMessages {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Those methods are needed to fix problems with java type system and kotlin variance
|
||||||
|
public static DiagnosticParameterRenderer<Map<Incompatible<MemberDescriptor>, Collection<MemberDescriptor>>> adaptGenerics1(DiagnosticParameterRenderer<Map<Incompatible<? extends MemberDescriptor>, ? extends Collection<? extends MemberDescriptor>>> renderer) {
|
||||||
|
return (obj, renderingContext) -> renderer.render((Map)obj, renderingContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DiagnosticParameterRenderer<List<Pair<MemberDescriptor, Map<Incompatible<MemberDescriptor>, Collection<MemberDescriptor>>>>> adaptGenerics2(DiagnosticParameterRenderer<List<? extends Pair<? extends MemberDescriptor, ? extends Map<ExpectActualCompatibility.Incompatible<? extends MemberDescriptor>, ? extends Collection<? extends MemberDescriptor>>>>> renderer) {
|
||||||
|
return (obj, renderingContext) -> renderer.render((List)obj, renderingContext);
|
||||||
|
}
|
||||||
|
|
||||||
private DefaultErrorMessages() {
|
private DefaultErrorMessages() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-7
@@ -18,13 +18,13 @@ package org.jetbrains.kotlin.diagnostics.rendering
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.MemberDescriptor
|
import org.jetbrains.kotlin.descriptors.MemberDescriptor
|
||||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver.Compatibility.Incompatible
|
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility.Incompatible
|
||||||
|
|
||||||
class PlatformIncompatibilityDiagnosticRenderer(
|
class PlatformIncompatibilityDiagnosticRenderer(
|
||||||
private val mode: MultiplatformDiagnosticRenderingMode
|
private val mode: MultiplatformDiagnosticRenderingMode
|
||||||
) : DiagnosticParameterRenderer<Map<Incompatible, Collection<MemberDescriptor>>> {
|
) : DiagnosticParameterRenderer<Map<Incompatible<MemberDescriptor>, Collection<MemberDescriptor>>> {
|
||||||
override fun render(
|
override fun render(
|
||||||
obj: Map<Incompatible, Collection<MemberDescriptor>>,
|
obj: Map<Incompatible<MemberDescriptor>, Collection<MemberDescriptor>>,
|
||||||
renderingContext: RenderingContext
|
renderingContext: RenderingContext
|
||||||
): String {
|
): String {
|
||||||
if (obj.isEmpty()) return ""
|
if (obj.isEmpty()) return ""
|
||||||
@@ -43,9 +43,9 @@ class PlatformIncompatibilityDiagnosticRenderer(
|
|||||||
|
|
||||||
class IncompatibleExpectedActualClassScopesRenderer(
|
class IncompatibleExpectedActualClassScopesRenderer(
|
||||||
private val mode: MultiplatformDiagnosticRenderingMode
|
private val mode: MultiplatformDiagnosticRenderingMode
|
||||||
) : DiagnosticParameterRenderer<List<Pair<MemberDescriptor, Map<Incompatible, Collection<MemberDescriptor>>>>> {
|
) : DiagnosticParameterRenderer<List<Pair<MemberDescriptor, Map<Incompatible<MemberDescriptor>, Collection<MemberDescriptor>>>>> {
|
||||||
override fun render(
|
override fun render(
|
||||||
obj: List<Pair<MemberDescriptor, Map<Incompatible, Collection<MemberDescriptor>>>>,
|
obj: List<Pair<MemberDescriptor, Map<Incompatible<MemberDescriptor>, Collection<MemberDescriptor>>>>,
|
||||||
renderingContext: RenderingContext
|
renderingContext: RenderingContext
|
||||||
): String {
|
): String {
|
||||||
if (obj.isEmpty()) return ""
|
if (obj.isEmpty()) return ""
|
||||||
@@ -82,7 +82,7 @@ open class MultiplatformDiagnosticRenderingMode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun StringBuilder.renderIncompatibilityInformation(
|
private fun StringBuilder.renderIncompatibilityInformation(
|
||||||
map: Map<Incompatible, Collection<MemberDescriptor>>,
|
map: Map<Incompatible<MemberDescriptor>, Collection<MemberDescriptor>>,
|
||||||
indent: String,
|
indent: String,
|
||||||
context: RenderingContext,
|
context: RenderingContext,
|
||||||
mode: MultiplatformDiagnosticRenderingMode
|
mode: MultiplatformDiagnosticRenderingMode
|
||||||
@@ -109,7 +109,7 @@ private fun StringBuilder.renderIncompatibilityInformation(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun StringBuilder.renderIncompatibleClassScopes(
|
private fun StringBuilder.renderIncompatibleClassScopes(
|
||||||
unfulfilled: List<Pair<MemberDescriptor, Map<Incompatible, Collection<MemberDescriptor>>>>,
|
unfulfilled: List<Pair<MemberDescriptor, Map<Incompatible<MemberDescriptor>, Collection<MemberDescriptor>>>>,
|
||||||
indent: String,
|
indent: String,
|
||||||
context: RenderingContext,
|
context: RenderingContext,
|
||||||
mode: MultiplatformDiagnosticRenderingMode
|
mode: MultiplatformDiagnosticRenderingMode
|
||||||
|
|||||||
+13
-14
@@ -33,10 +33,9 @@ import org.jetbrains.kotlin.resolve.constants.ConstantValue
|
|||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isAnnotationConstructor
|
import org.jetbrains.kotlin.resolve.descriptorUtil.isAnnotationConstructor
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isPrimaryConstructorOfInlineClass
|
import org.jetbrains.kotlin.resolve.descriptorUtil.isPrimaryConstructorOfInlineClass
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
|
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility
|
||||||
|
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility.*
|
||||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver
|
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver
|
||||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver.Compatibility
|
|
||||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver.Compatibility.Compatible
|
|
||||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver.Compatibility.Incompatible
|
|
||||||
import org.jetbrains.kotlin.resolve.multiplatform.ModuleFilter
|
import org.jetbrains.kotlin.resolve.multiplatform.ModuleFilter
|
||||||
import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil
|
import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil
|
||||||
import org.jetbrains.kotlin.resolve.source.PsiSourceFile
|
import org.jetbrains.kotlin.resolve.source.PsiSourceFile
|
||||||
@@ -136,7 +135,7 @@ class ExpectedActualDeclarationChecker(
|
|||||||
val compatibility = path.nodes
|
val compatibility = path.nodes
|
||||||
.mapNotNull { ExpectedActualResolver.findActualForExpected(descriptor, it, moduleVisibilityFilter) }
|
.mapNotNull { ExpectedActualResolver.findActualForExpected(descriptor, it, moduleVisibilityFilter) }
|
||||||
.ifEmpty { return }
|
.ifEmpty { return }
|
||||||
.fold(LinkedHashMap<Compatibility, List<MemberDescriptor>>()) { resultMap, partialMap ->
|
.fold(LinkedHashMap<ExpectActualCompatibility<MemberDescriptor>, List<MemberDescriptor>>()) { resultMap, partialMap ->
|
||||||
resultMap.apply { putAll(partialMap) }
|
resultMap.apply { putAll(partialMap) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,7 +179,7 @@ class ExpectedActualDeclarationChecker(
|
|||||||
) {
|
) {
|
||||||
assert(compatibility.keys.all { it is Incompatible })
|
assert(compatibility.keys.all { it is Incompatible })
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
val incompatibility = compatibility as Map<Incompatible, Collection<MemberDescriptor>>
|
val incompatibility = compatibility as Map<Incompatible<MemberDescriptor>, Collection<MemberDescriptor>>
|
||||||
trace.report(Errors.NO_ACTUAL_FOR_EXPECT.on(reportOn, descriptor, module, incompatibility))
|
trace.report(Errors.NO_ACTUAL_FOR_EXPECT.on(reportOn, descriptor, module, incompatibility))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -188,14 +187,14 @@ class ExpectedActualDeclarationChecker(
|
|||||||
// Here we have exactly one compatible actual and/or some weakly incompatible. In either case, we don't report anything on expect
|
// Here we have exactly one compatible actual and/or some weakly incompatible. In either case, we don't report anything on expect
|
||||||
val actualMembers = compatibility.asSequence()
|
val actualMembers = compatibility.asSequence()
|
||||||
.filter { (compatibility, _) ->
|
.filter { (compatibility, _) ->
|
||||||
compatibility is Compatible || (compatibility is Incompatible && compatibility.kind != Compatibility.IncompatibilityKind.STRONG)
|
compatibility is Compatible || (compatibility is Incompatible && compatibility.kind != IncompatibilityKind.STRONG)
|
||||||
}.flatMap { it.value.asSequence() }
|
}.flatMap { it.value.asSequence() }
|
||||||
|
|
||||||
expectActualTracker.reportExpectActual(expected = descriptor, actualMembers = actualMembers)
|
expectActualTracker.reportExpectActual(expected = descriptor, actualMembers = actualMembers)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun MemberDescriptor.hasNoActualWithDiagnostic(
|
private fun MemberDescriptor.hasNoActualWithDiagnostic(
|
||||||
compatibility: Map<Compatibility, List<MemberDescriptor>>
|
compatibility: Map<ExpectActualCompatibility<MemberDescriptor>, List<MemberDescriptor>>
|
||||||
): Boolean {
|
): Boolean {
|
||||||
return compatibility.values.flatMapTo(hashSetOf()) { it }.all { actual ->
|
return compatibility.values.flatMapTo(hashSetOf()) { it }.all { actual ->
|
||||||
val expectedOnes = ExpectedActualResolver.findExpectedForActual(actual, module)
|
val expectedOnes = ExpectedActualResolver.findExpectedForActual(actual, module)
|
||||||
@@ -257,7 +256,7 @@ class ExpectedActualDeclarationChecker(
|
|||||||
// This is needed only to reduce the number of errors. Incompatibility errors for those members will be reported
|
// This is needed only to reduce the number of errors. Incompatibility errors for those members will be reported
|
||||||
// later when this checker is called for them
|
// later when this checker is called for them
|
||||||
fun hasSingleActualSuspect(
|
fun hasSingleActualSuspect(
|
||||||
expectedWithIncompatibility: Pair<MemberDescriptor, Map<Incompatible, Collection<MemberDescriptor>>>
|
expectedWithIncompatibility: Pair<MemberDescriptor, Map<Incompatible<MemberDescriptor>, Collection<MemberDescriptor>>>
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val (expectedMember, incompatibility) = expectedWithIncompatibility
|
val (expectedMember, incompatibility) = expectedWithIncompatibility
|
||||||
val actualMember = incompatibility.values.singleOrNull()?.singleOrNull()
|
val actualMember = incompatibility.values.singleOrNull()?.singleOrNull()
|
||||||
@@ -285,7 +284,7 @@ class ExpectedActualDeclarationChecker(
|
|||||||
} else if (Compatible !in compatibility) {
|
} else if (Compatible !in compatibility) {
|
||||||
assert(compatibility.keys.all { it is Incompatible })
|
assert(compatibility.keys.all { it is Incompatible })
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
val incompatibility = compatibility as Map<Incompatible, Collection<MemberDescriptor>>
|
val incompatibility = compatibility as Map<Incompatible<MemberDescriptor>, Collection<MemberDescriptor>>
|
||||||
trace.report(Errors.ACTUAL_WITHOUT_EXPECT.on(reportOn, descriptor, incompatibility))
|
trace.report(Errors.ACTUAL_WITHOUT_EXPECT.on(reportOn, descriptor, incompatibility))
|
||||||
} else {
|
} else {
|
||||||
val expected = compatibility[Compatible]!!.first()
|
val expected = compatibility[Compatible]!!.first()
|
||||||
@@ -302,7 +301,7 @@ class ExpectedActualDeclarationChecker(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun checkAmbiguousExpects(
|
private fun checkAmbiguousExpects(
|
||||||
compatibility: Map<Compatibility, List<MemberDescriptor>>,
|
compatibility: Map<ExpectActualCompatibility<MemberDescriptor>, List<MemberDescriptor>>,
|
||||||
trace: BindingTrace,
|
trace: BindingTrace,
|
||||||
reportOn: KtNamedDeclaration,
|
reportOn: KtNamedDeclaration,
|
||||||
descriptor: MemberDescriptor
|
descriptor: MemberDescriptor
|
||||||
@@ -322,9 +321,9 @@ class ExpectedActualDeclarationChecker(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Compatibility.isCompatibleOrWeakCompatible() =
|
private fun ExpectActualCompatibility<MemberDescriptor>.isCompatibleOrWeakCompatible() =
|
||||||
this is Compatible ||
|
this is Compatible ||
|
||||||
this is Incompatible && kind == ExpectedActualResolver.Compatibility.IncompatibilityKind.WEAK
|
this is Incompatible && kind == IncompatibilityKind.WEAK
|
||||||
|
|
||||||
// we don't require `actual` modifier on
|
// we don't require `actual` modifier on
|
||||||
// - annotation constructors, because annotation classes can only have one constructor
|
// - annotation constructors, because annotation classes can only have one constructor
|
||||||
@@ -390,7 +389,7 @@ class ExpectedActualDeclarationChecker(
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun Map<out Compatibility, Collection<MemberDescriptor>>.allStrongIncompatibilities(): Boolean =
|
fun Map<out ExpectActualCompatibility<MemberDescriptor>, Collection<MemberDescriptor>>.allStrongIncompatibilities(): Boolean =
|
||||||
this.keys.all { it is Incompatible && it.kind == Compatibility.IncompatibilityKind.STRONG }
|
this.keys.all { it is Incompatible && it.kind == IncompatibilityKind.STRONG }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+90
@@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.resolve.multiplatform
|
||||||
|
|
||||||
|
sealed class ExpectActualCompatibility<out D> {
|
||||||
|
// For IncompatibilityKind.STRONG `actual` declaration is considered as overload and error reports on expected declaration
|
||||||
|
enum class IncompatibilityKind {
|
||||||
|
WEAK, STRONG
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note that the reason is used in the diagnostic output, see PlatformIncompatibilityDiagnosticRenderer
|
||||||
|
sealed class Incompatible<out D>(
|
||||||
|
val reason: String?,
|
||||||
|
val kind: IncompatibilityKind = IncompatibilityKind.WEAK
|
||||||
|
) : ExpectActualCompatibility<D>() {
|
||||||
|
// Callables
|
||||||
|
|
||||||
|
object CallableKind : Incompatible<Nothing>(
|
||||||
|
"callable kinds are different (function vs property)",
|
||||||
|
IncompatibilityKind.STRONG
|
||||||
|
)
|
||||||
|
|
||||||
|
object ParameterShape : Incompatible<Nothing>(
|
||||||
|
"parameter shapes are different (extension vs non-extension)",
|
||||||
|
IncompatibilityKind.STRONG
|
||||||
|
)
|
||||||
|
|
||||||
|
object ParameterCount : Incompatible<Nothing>("number of value parameters is different", IncompatibilityKind.STRONG)
|
||||||
|
object TypeParameterCount : Incompatible<Nothing>("number of type parameters is different", IncompatibilityKind.STRONG)
|
||||||
|
|
||||||
|
object ParameterTypes : Incompatible<Nothing>("parameter types are different", IncompatibilityKind.STRONG)
|
||||||
|
object ReturnType : Incompatible<Nothing>("return type is different", IncompatibilityKind.STRONG)
|
||||||
|
|
||||||
|
object ParameterNames : Incompatible<Nothing>("parameter names are different")
|
||||||
|
object TypeParameterNames : Incompatible<Nothing>("names of type parameters are different")
|
||||||
|
|
||||||
|
object ValueParameterVararg : Incompatible<Nothing>("some value parameter is vararg in one declaration and non-vararg in the other")
|
||||||
|
object ValueParameterNoinline : Incompatible<Nothing>(
|
||||||
|
"some value parameter is noinline in one declaration and not noinline in the other"
|
||||||
|
)
|
||||||
|
|
||||||
|
object ValueParameterCrossinline : Incompatible<Nothing>(
|
||||||
|
"some value parameter is crossinline in one declaration and not crossinline in the other"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Functions
|
||||||
|
|
||||||
|
object FunctionModifiersDifferent : Incompatible<Nothing>("modifiers are different (suspend)")
|
||||||
|
object FunctionModifiersNotSubset : Incompatible<Nothing>(
|
||||||
|
"some modifiers on expected declaration are missing on the actual one (external, infix, inline, operator, tailrec)"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Properties
|
||||||
|
|
||||||
|
object PropertyKind : Incompatible<Nothing>("property kinds are different (val vs var)")
|
||||||
|
object PropertyModifiers : Incompatible<Nothing>("modifiers are different (const, lateinit)")
|
||||||
|
|
||||||
|
// Classifiers
|
||||||
|
|
||||||
|
object ClassKind : Incompatible<Nothing>("class kinds are different (class, interface, object, enum, annotation)")
|
||||||
|
|
||||||
|
object ClassModifiers : Incompatible<Nothing>("modifiers are different (companion, inner, inline)")
|
||||||
|
|
||||||
|
object Supertypes : Incompatible<Nothing>("some supertypes are missing in the actual declaration")
|
||||||
|
|
||||||
|
class ClassScopes<D>(
|
||||||
|
val unfulfilled: List<Pair<D, Map<Incompatible<D>, Collection<D>>>>
|
||||||
|
) : Incompatible<D>("some expected members have no actual ones")
|
||||||
|
|
||||||
|
object EnumEntries : Incompatible<Nothing>("some entries from expected enum are missing in the actual enum")
|
||||||
|
|
||||||
|
// Common
|
||||||
|
|
||||||
|
object Modality : Incompatible<Nothing>("modality is different")
|
||||||
|
object Visibility : Incompatible<Nothing>("visibility is different")
|
||||||
|
|
||||||
|
object TypeParameterUpperBounds : Incompatible<Nothing>("upper bounds of type parameters are different", IncompatibilityKind.STRONG)
|
||||||
|
object TypeParameterVariance : Incompatible<Nothing>("declaration-site variances of type parameters are different")
|
||||||
|
object TypeParameterReified : Incompatible<Nothing>(
|
||||||
|
"some type parameter is reified in one declaration and non-reified in the other"
|
||||||
|
)
|
||||||
|
|
||||||
|
object Unknown : Incompatible<Nothing>(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
object Compatible : ExpectActualCompatibility<Nothing>()
|
||||||
|
}
|
||||||
+12
-78
@@ -13,8 +13,8 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils
|
|||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isAnnotationConstructor
|
import org.jetbrains.kotlin.resolve.descriptorUtil.isAnnotationConstructor
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver.Compatibility.Compatible
|
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility.Compatible
|
||||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver.Compatibility.Incompatible
|
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility.Incompatible
|
||||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||||
import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
|
import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
|
||||||
@@ -49,7 +49,7 @@ object ExpectedActualResolver {
|
|||||||
expected: MemberDescriptor,
|
expected: MemberDescriptor,
|
||||||
platformModule: ModuleDescriptor,
|
platformModule: ModuleDescriptor,
|
||||||
moduleVisibilityFilter: ModuleFilter = onlyFromThisModule(platformModule)
|
moduleVisibilityFilter: ModuleFilter = onlyFromThisModule(platformModule)
|
||||||
): Map<Compatibility, List<MemberDescriptor>>? {
|
): Map<ExpectActualCompatibility<MemberDescriptor>, List<MemberDescriptor>>? {
|
||||||
return when (expected) {
|
return when (expected) {
|
||||||
is CallableMemberDescriptor -> {
|
is CallableMemberDescriptor -> {
|
||||||
expected.findNamesakesFromModule(platformModule, moduleVisibilityFilter).filter { actual ->
|
expected.findNamesakesFromModule(platformModule, moduleVisibilityFilter).filter { actual ->
|
||||||
@@ -78,7 +78,7 @@ object ExpectedActualResolver {
|
|||||||
actual: MemberDescriptor,
|
actual: MemberDescriptor,
|
||||||
commonModule: ModuleDescriptor,
|
commonModule: ModuleDescriptor,
|
||||||
moduleFilter: (ModuleDescriptor) -> Boolean = onlyFromThisModule(commonModule)
|
moduleFilter: (ModuleDescriptor) -> Boolean = onlyFromThisModule(commonModule)
|
||||||
): Map<Compatibility, List<MemberDescriptor>>? {
|
): Map<ExpectActualCompatibility<MemberDescriptor>, List<MemberDescriptor>>? {
|
||||||
return when (actual) {
|
return when (actual) {
|
||||||
is CallableMemberDescriptor -> {
|
is CallableMemberDescriptor -> {
|
||||||
val container = actual.containingDeclaration
|
val container = actual.containingDeclaration
|
||||||
@@ -180,79 +180,13 @@ object ExpectedActualResolver {
|
|||||||
return classifiers
|
return classifiers
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class Compatibility {
|
|
||||||
// For IncompatibilityKind.STRONG `actual` declaration is considered as overload and error reports on expected declaration
|
|
||||||
enum class IncompatibilityKind {
|
|
||||||
WEAK, STRONG
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note that the reason is used in the diagnostic output, see PlatformIncompatibilityDiagnosticRenderer
|
|
||||||
sealed class Incompatible(val reason: String?, val kind: IncompatibilityKind = IncompatibilityKind.WEAK) : Compatibility() {
|
|
||||||
// Callables
|
|
||||||
|
|
||||||
object CallableKind : Incompatible("callable kinds are different (function vs property)", IncompatibilityKind.STRONG)
|
|
||||||
|
|
||||||
object ParameterShape : Incompatible("parameter shapes are different (extension vs non-extension)", IncompatibilityKind.STRONG)
|
|
||||||
|
|
||||||
object ParameterCount : Incompatible("number of value parameters is different", IncompatibilityKind.STRONG)
|
|
||||||
object TypeParameterCount : Incompatible("number of type parameters is different", IncompatibilityKind.STRONG)
|
|
||||||
|
|
||||||
object ParameterTypes : Incompatible("parameter types are different", IncompatibilityKind.STRONG)
|
|
||||||
object ReturnType : Incompatible("return type is different", IncompatibilityKind.STRONG)
|
|
||||||
|
|
||||||
object ParameterNames : Incompatible("parameter names are different")
|
|
||||||
object TypeParameterNames : Incompatible("names of type parameters are different")
|
|
||||||
|
|
||||||
object ValueParameterVararg : Incompatible("some value parameter is vararg in one declaration and non-vararg in the other")
|
|
||||||
object ValueParameterNoinline : Incompatible("some value parameter is noinline in one declaration and not noinline in the other")
|
|
||||||
object ValueParameterCrossinline : Incompatible("some value parameter is crossinline in one declaration and not crossinline in the other")
|
|
||||||
|
|
||||||
// Functions
|
|
||||||
|
|
||||||
object FunctionModifiersDifferent : Incompatible("modifiers are different (suspend)")
|
|
||||||
object FunctionModifiersNotSubset : Incompatible("some modifiers on expected declaration are missing on the actual one (external, infix, inline, operator, tailrec)")
|
|
||||||
|
|
||||||
// Properties
|
|
||||||
|
|
||||||
object PropertyKind : Incompatible("property kinds are different (val vs var)")
|
|
||||||
object PropertyModifiers : Incompatible("modifiers are different (const, lateinit)")
|
|
||||||
|
|
||||||
// Classifiers
|
|
||||||
|
|
||||||
object ClassKind : Incompatible("class kinds are different (class, interface, object, enum, annotation)")
|
|
||||||
|
|
||||||
object ClassModifiers : Incompatible("modifiers are different (companion, inner, inline)")
|
|
||||||
|
|
||||||
object Supertypes : Incompatible("some supertypes are missing in the actual declaration")
|
|
||||||
|
|
||||||
class ClassScopes(
|
|
||||||
val unfulfilled: List<Pair<MemberDescriptor, Map<Incompatible, Collection<MemberDescriptor>>>>
|
|
||||||
) : Incompatible("some expected members have no actual ones")
|
|
||||||
|
|
||||||
object EnumEntries : Incompatible("some entries from expected enum are missing in the actual enum")
|
|
||||||
|
|
||||||
// Common
|
|
||||||
|
|
||||||
object Modality : Incompatible("modality is different")
|
|
||||||
object Visibility : Incompatible("visibility is different")
|
|
||||||
|
|
||||||
object TypeParameterUpperBounds : Incompatible("upper bounds of type parameters are different", IncompatibilityKind.STRONG)
|
|
||||||
object TypeParameterVariance : Incompatible("declaration-site variances of type parameters are different")
|
|
||||||
object TypeParameterReified : Incompatible("some type parameter is reified in one declaration and non-reified in the other")
|
|
||||||
|
|
||||||
object Unknown : Incompatible(null)
|
|
||||||
}
|
|
||||||
|
|
||||||
object Compatible : Compatibility()
|
|
||||||
}
|
|
||||||
|
|
||||||
// a is the declaration in common code, b is the definition in the platform-specific code
|
// a is the declaration in common code, b is the definition in the platform-specific code
|
||||||
private fun areCompatibleCallables(
|
private fun areCompatibleCallables(
|
||||||
a: CallableMemberDescriptor,
|
a: CallableMemberDescriptor,
|
||||||
b: CallableMemberDescriptor,
|
b: CallableMemberDescriptor,
|
||||||
platformModule: ModuleDescriptor = b.module,
|
platformModule: ModuleDescriptor = b.module,
|
||||||
parentSubstitutor: Substitutor? = null
|
parentSubstitutor: Substitutor? = null
|
||||||
): Compatibility {
|
): ExpectActualCompatibility<MemberDescriptor> {
|
||||||
assert(a.name == b.name) {
|
assert(a.name == b.name) {
|
||||||
"This function should be invoked only for declarations with the same name: $a, $b"
|
"This function should be invoked only for declarations with the same name: $a, $b"
|
||||||
}
|
}
|
||||||
@@ -376,7 +310,7 @@ object ExpectedActualResolver {
|
|||||||
b: List<TypeParameterDescriptor>,
|
b: List<TypeParameterDescriptor>,
|
||||||
platformModule: ModuleDescriptor,
|
platformModule: ModuleDescriptor,
|
||||||
substitutor: Substitutor
|
substitutor: Substitutor
|
||||||
): Compatibility {
|
): ExpectActualCompatibility<MemberDescriptor> {
|
||||||
for (i in a.indices) {
|
for (i in a.indices) {
|
||||||
val aBounds = a[i].upperBounds
|
val aBounds = a[i].upperBounds
|
||||||
val bBounds = b[i].upperBounds
|
val bBounds = b[i].upperBounds
|
||||||
@@ -393,7 +327,7 @@ object ExpectedActualResolver {
|
|||||||
return Compatible
|
return Compatible
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun areCompatibleFunctions(a: FunctionDescriptor, b: FunctionDescriptor): Compatibility {
|
private fun areCompatibleFunctions(a: FunctionDescriptor, b: FunctionDescriptor): ExpectActualCompatibility<MemberDescriptor> {
|
||||||
if (!equalBy(a, b) { f -> f.isSuspend }) return Incompatible.FunctionModifiersDifferent
|
if (!equalBy(a, b) { f -> f.isSuspend }) return Incompatible.FunctionModifiersDifferent
|
||||||
|
|
||||||
if (a.isExternal && !b.isExternal ||
|
if (a.isExternal && !b.isExternal ||
|
||||||
@@ -405,14 +339,14 @@ object ExpectedActualResolver {
|
|||||||
return Compatible
|
return Compatible
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun areCompatibleProperties(a: PropertyDescriptor, b: PropertyDescriptor): Compatibility {
|
private fun areCompatibleProperties(a: PropertyDescriptor, b: PropertyDescriptor): ExpectActualCompatibility<MemberDescriptor> {
|
||||||
if (!equalBy(a, b) { p -> p.isVar }) return Incompatible.PropertyKind
|
if (!equalBy(a, b) { p -> p.isVar }) return Incompatible.PropertyKind
|
||||||
if (!equalBy(a, b) { p -> listOf(p.isConst, p.isLateInit) }) return Incompatible.PropertyModifiers
|
if (!equalBy(a, b) { p -> listOf(p.isConst, p.isLateInit) }) return Incompatible.PropertyModifiers
|
||||||
|
|
||||||
return Compatible
|
return Compatible
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun areCompatibleClassifiers(a: ClassDescriptor, other: ClassifierDescriptor): Compatibility {
|
private fun areCompatibleClassifiers(a: ClassDescriptor, other: ClassifierDescriptor): ExpectActualCompatibility<MemberDescriptor> {
|
||||||
// Can't check FQ names here because nested expected class may be implemented via actual typealias's expansion with the other FQ name
|
// Can't check FQ names here because nested expected class may be implemented via actual typealias's expansion with the other FQ name
|
||||||
assert(a.name == other.name) { "This function should be invoked only for declarations with the same name: $a, $other" }
|
assert(a.name == other.name) { "This function should be invoked only for declarations with the same name: $a, $other" }
|
||||||
|
|
||||||
@@ -476,8 +410,8 @@ object ExpectedActualResolver {
|
|||||||
b: ClassDescriptor,
|
b: ClassDescriptor,
|
||||||
platformModule: ModuleDescriptor,
|
platformModule: ModuleDescriptor,
|
||||||
substitutor: Substitutor
|
substitutor: Substitutor
|
||||||
): Compatibility {
|
): ExpectActualCompatibility<MemberDescriptor> {
|
||||||
val unfulfilled = arrayListOf<Pair<MemberDescriptor, Map<Incompatible, MutableCollection<MemberDescriptor>>>>()
|
val unfulfilled = arrayListOf<Pair<MemberDescriptor, Map<Incompatible<MemberDescriptor>, MutableCollection<MemberDescriptor>>>>()
|
||||||
|
|
||||||
val bMembersByName = b.getMembers().groupBy { it.name }
|
val bMembersByName = b.getMembers().groupBy { it.name }
|
||||||
|
|
||||||
@@ -500,7 +434,7 @@ object ExpectedActualResolver {
|
|||||||
}
|
}
|
||||||
if (mapping.values.any { it == Compatible }) continue
|
if (mapping.values.any { it == Compatible }) continue
|
||||||
|
|
||||||
val incompatibilityMap = mutableMapOf<Incompatible, MutableCollection<MemberDescriptor>>()
|
val incompatibilityMap = mutableMapOf<Incompatible<MemberDescriptor>, MutableCollection<MemberDescriptor>>()
|
||||||
for ((descriptor, compatibility) in mapping) {
|
for ((descriptor, compatibility) in mapping) {
|
||||||
when (compatibility) {
|
when (compatibility) {
|
||||||
Compatible -> continue@outer
|
Compatible -> continue@outer
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
|||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||||
|
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility
|
||||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver
|
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver
|
||||||
|
|
||||||
internal fun MemberDescriptor.expectedDescriptors() =
|
internal fun MemberDescriptor.expectedDescriptors() =
|
||||||
@@ -74,7 +75,7 @@ fun ModuleDescriptor.hasDeclarationOf(descriptor: MemberDescriptor) = declaratio
|
|||||||
private fun ModuleDescriptor.declarationOf(descriptor: MemberDescriptor): DeclarationDescriptor? =
|
private fun ModuleDescriptor.declarationOf(descriptor: MemberDescriptor): DeclarationDescriptor? =
|
||||||
with(ExpectedActualResolver) {
|
with(ExpectedActualResolver) {
|
||||||
val expectedCompatibilityMap = findExpectedForActual(descriptor, this@declarationOf)
|
val expectedCompatibilityMap = findExpectedForActual(descriptor, this@declarationOf)
|
||||||
expectedCompatibilityMap?.get(ExpectedActualResolver.Compatibility.Compatible)?.firstOrNull()
|
expectedCompatibilityMap?.get(ExpectActualCompatibility.Compatible)?.firstOrNull()
|
||||||
?: expectedCompatibilityMap?.values?.flatten()?.firstOrNull()
|
?: expectedCompatibilityMap?.values?.flatten()?.firstOrNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker.Co
|
|||||||
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
|
||||||
import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil
|
import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil
|
||||||
|
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility
|
||||||
|
|
||||||
class OptionalExpectationInspection : AbstractKotlinInspection() {
|
class OptionalExpectationInspection : AbstractKotlinInspection() {
|
||||||
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession) =
|
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession) =
|
||||||
@@ -43,12 +44,12 @@ class OptionalExpectationInspection : AbstractKotlinInspection() {
|
|||||||
for (actualModuleDescriptor in implementingModules) {
|
for (actualModuleDescriptor in implementingModules) {
|
||||||
val compatibility = ExpectedActualResolver.findActualForExpected(descriptor, actualModuleDescriptor) ?: continue
|
val compatibility = ExpectedActualResolver.findActualForExpected(descriptor, actualModuleDescriptor) ?: continue
|
||||||
if (!compatibility.allStrongIncompatibilities() &&
|
if (!compatibility.allStrongIncompatibilities() &&
|
||||||
(ExpectedActualResolver.Compatibility.Compatible in compatibility ||
|
(ExpectActualCompatibility.Compatible in compatibility ||
|
||||||
!compatibility.values.flatMapTo(
|
!compatibility.values.flatMapTo(
|
||||||
hashSetOf()
|
hashSetOf()
|
||||||
) { it }.all { actual ->
|
) { it }.all { actual ->
|
||||||
val expectedOnes = ExpectedActualResolver.findExpectedForActual(actual, descriptor.module)
|
val expectedOnes = ExpectedActualResolver.findExpectedForActual(actual, descriptor.module)
|
||||||
expectedOnes != null && ExpectedActualResolver.Compatibility.Compatible in expectedOnes.keys
|
expectedOnes != null && ExpectActualCompatibility.Compatible in expectedOnes.keys
|
||||||
})
|
})
|
||||||
) continue
|
) continue
|
||||||
val platform = actualModuleDescriptor.platform ?: continue
|
val platform = actualModuleDescriptor.platform ?: continue
|
||||||
|
|||||||
Reference in New Issue
Block a user