Move ExpectActualCompatibility to :compiler:resolution.common

This commit is contained in:
Dmitriy Novozhilov
2021-05-21 15:14:03 +03:00
committed by teamcityserver
parent 950db81aa4
commit 6e83820f97
9 changed files with 153 additions and 117 deletions
@@ -29,7 +29,7 @@ import org.jetbrains.kotlin.resolve.VarianceConflictDiagnosticData;
import org.jetbrains.kotlin.resolve.calls.inference.InferenceErrorData;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
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.types.KotlinType;
@@ -704,10 +704,10 @@ public interface Errors {
DiagnosticFactory0<PsiElement> EXPECTED_FUNCTION_SOURCE_WITH_DEFAULT_ARGUMENTS_NOT_FOUND = DiagnosticFactory0.create(ERROR);
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);
DiagnosticFactory2<KtNamedDeclaration, MemberDescriptor,
Map<Incompatible, Collection<MemberDescriptor>>> ACTUAL_WITHOUT_EXPECT =
Map<Incompatible<MemberDescriptor>, Collection<MemberDescriptor>>> ACTUAL_WITHOUT_EXPECT =
DiagnosticFactory2.create(ERROR, INCOMPATIBLE_DECLARATION);
DiagnosticFactory2<KtNamedDeclaration, DeclarationDescriptor, Collection<ModuleDescriptor>> AMBIGUOUS_ACTUALS =
DiagnosticFactory2.create(ERROR, INCOMPATIBLE_DECLARATION);
@@ -715,7 +715,7 @@ public interface Errors {
DiagnosticFactory2.create(ERROR, INCOMPATIBLE_DECLARATION);
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);
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 org.jetbrains.kotlin.KtNodeTypes
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.NO_ACTUAL_FOR_EXPECT
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.psi.*
import org.jetbrains.kotlin.psi.psiUtil.*
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver.Compatibility.Incompatible
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver.Compatibility.Incompatible.*
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility.Incompatible
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility.Incompatible.*
import org.jetbrains.kotlin.utils.sure
object PositioningStrategies {
@@ -114,7 +115,7 @@ object PositioningStrategies {
}
}
private val ParametrizedDiagnostic<out KtNamedDeclaration>.firstIncompatibility: Incompatible?
private val ParametrizedDiagnostic<out KtNamedDeclaration>.firstIncompatibility: Incompatible<MemberDescriptor>?
get() {
val map = when (factory) {
NO_ACTUAL_FOR_EXPECT ->
@@ -11,20 +11,21 @@ import kotlin.collections.CollectionsKt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.config.LanguageVersion;
import org.jetbrains.kotlin.descriptors.MemberDescriptor;
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory;
import org.jetbrains.kotlin.diagnostics.Errors;
import org.jetbrains.kotlin.diagnostics.UnboundDiagnostic;
import org.jetbrains.kotlin.metadata.deserialization.VersionRequirement;
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.util.OperatorNameConventions;
import org.jetbrains.kotlin.utils.addToStdlib.AddToStdlibKt;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Collections;
import java.util.List;
import java.util.ServiceLoader;
import java.util.*;
import static org.jetbrains.kotlin.diagnostics.Errors.*;
import static org.jetbrains.kotlin.diagnostics.rendering.Renderers.*;
@@ -307,16 +308,16 @@ public class DefaultErrorMessages {
"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,
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,
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(
MODULE));
MAP.put(AMBIGUOUS_EXPECTS, "{0} has several compatible expect declarations in modules {1}", CAPITALIZED_DECLARATION_NAME_WITH_KIND_AND_PLATFORM, commaSeparated(
MODULE));
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(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() {
}
}
@@ -18,13 +18,13 @@ package org.jetbrains.kotlin.diagnostics.rendering
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
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(
private val mode: MultiplatformDiagnosticRenderingMode
) : DiagnosticParameterRenderer<Map<Incompatible, Collection<MemberDescriptor>>> {
) : DiagnosticParameterRenderer<Map<Incompatible<MemberDescriptor>, Collection<MemberDescriptor>>> {
override fun render(
obj: Map<Incompatible, Collection<MemberDescriptor>>,
obj: Map<Incompatible<MemberDescriptor>, Collection<MemberDescriptor>>,
renderingContext: RenderingContext
): String {
if (obj.isEmpty()) return ""
@@ -43,9 +43,9 @@ class PlatformIncompatibilityDiagnosticRenderer(
class IncompatibleExpectedActualClassScopesRenderer(
private val mode: MultiplatformDiagnosticRenderingMode
) : DiagnosticParameterRenderer<List<Pair<MemberDescriptor, Map<Incompatible, Collection<MemberDescriptor>>>>> {
) : DiagnosticParameterRenderer<List<Pair<MemberDescriptor, Map<Incompatible<MemberDescriptor>, Collection<MemberDescriptor>>>>> {
override fun render(
obj: List<Pair<MemberDescriptor, Map<Incompatible, Collection<MemberDescriptor>>>>,
obj: List<Pair<MemberDescriptor, Map<Incompatible<MemberDescriptor>, Collection<MemberDescriptor>>>>,
renderingContext: RenderingContext
): String {
if (obj.isEmpty()) return ""
@@ -82,7 +82,7 @@ open class MultiplatformDiagnosticRenderingMode {
}
private fun StringBuilder.renderIncompatibilityInformation(
map: Map<Incompatible, Collection<MemberDescriptor>>,
map: Map<Incompatible<MemberDescriptor>, Collection<MemberDescriptor>>,
indent: String,
context: RenderingContext,
mode: MultiplatformDiagnosticRenderingMode
@@ -109,7 +109,7 @@ private fun StringBuilder.renderIncompatibilityInformation(
}
private fun StringBuilder.renderIncompatibleClassScopes(
unfulfilled: List<Pair<MemberDescriptor, Map<Incompatible, Collection<MemberDescriptor>>>>,
unfulfilled: List<Pair<MemberDescriptor, Map<Incompatible<MemberDescriptor>, Collection<MemberDescriptor>>>>,
indent: String,
context: RenderingContext,
mode: MultiplatformDiagnosticRenderingMode
@@ -33,10 +33,9 @@ import org.jetbrains.kotlin.resolve.constants.ConstantValue
import org.jetbrains.kotlin.resolve.descriptorUtil.isAnnotationConstructor
import org.jetbrains.kotlin.resolve.descriptorUtil.isPrimaryConstructorOfInlineClass
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility.*
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.OptionalAnnotationUtil
import org.jetbrains.kotlin.resolve.source.PsiSourceFile
@@ -136,7 +135,7 @@ class ExpectedActualDeclarationChecker(
val compatibility = path.nodes
.mapNotNull { ExpectedActualResolver.findActualForExpected(descriptor, it, moduleVisibilityFilter) }
.ifEmpty { return }
.fold(LinkedHashMap<Compatibility, List<MemberDescriptor>>()) { resultMap, partialMap ->
.fold(LinkedHashMap<ExpectActualCompatibility<MemberDescriptor>, List<MemberDescriptor>>()) { resultMap, partialMap ->
resultMap.apply { putAll(partialMap) }
}
@@ -180,7 +179,7 @@ class ExpectedActualDeclarationChecker(
) {
assert(compatibility.keys.all { it is Incompatible })
@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))
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
val actualMembers = compatibility.asSequence()
.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() }
expectActualTracker.reportExpectActual(expected = descriptor, actualMembers = actualMembers)
}
private fun MemberDescriptor.hasNoActualWithDiagnostic(
compatibility: Map<Compatibility, List<MemberDescriptor>>
compatibility: Map<ExpectActualCompatibility<MemberDescriptor>, List<MemberDescriptor>>
): Boolean {
return compatibility.values.flatMapTo(hashSetOf()) { it }.all { actual ->
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
// later when this checker is called for them
fun hasSingleActualSuspect(
expectedWithIncompatibility: Pair<MemberDescriptor, Map<Incompatible, Collection<MemberDescriptor>>>
expectedWithIncompatibility: Pair<MemberDescriptor, Map<Incompatible<MemberDescriptor>, Collection<MemberDescriptor>>>
): Boolean {
val (expectedMember, incompatibility) = expectedWithIncompatibility
val actualMember = incompatibility.values.singleOrNull()?.singleOrNull()
@@ -285,7 +284,7 @@ class ExpectedActualDeclarationChecker(
} else if (Compatible !in compatibility) {
assert(compatibility.keys.all { it is Incompatible })
@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))
} else {
val expected = compatibility[Compatible]!!.first()
@@ -302,7 +301,7 @@ class ExpectedActualDeclarationChecker(
}
private fun checkAmbiguousExpects(
compatibility: Map<Compatibility, List<MemberDescriptor>>,
compatibility: Map<ExpectActualCompatibility<MemberDescriptor>, List<MemberDescriptor>>,
trace: BindingTrace,
reportOn: KtNamedDeclaration,
descriptor: MemberDescriptor
@@ -322,9 +321,9 @@ class ExpectedActualDeclarationChecker(
}
}
private fun Compatibility.isCompatibleOrWeakCompatible() =
private fun ExpectActualCompatibility<MemberDescriptor>.isCompatibleOrWeakCompatible() =
this is Compatible ||
this is Incompatible && kind == ExpectedActualResolver.Compatibility.IncompatibilityKind.WEAK
this is Incompatible && kind == IncompatibilityKind.WEAK
// we don't require `actual` modifier on
// - annotation constructors, because annotation classes can only have one constructor
@@ -390,7 +389,7 @@ class ExpectedActualDeclarationChecker(
}
companion object {
fun Map<out Compatibility, Collection<MemberDescriptor>>.allStrongIncompatibilities(): Boolean =
this.keys.all { it is Incompatible && it.kind == Compatibility.IncompatibilityKind.STRONG }
fun Map<out ExpectActualCompatibility<MemberDescriptor>, Collection<MemberDescriptor>>.allStrongIncompatibilities(): Boolean =
this.keys.all { it is Incompatible && it.kind == IncompatibilityKind.STRONG }
}
}