[FIR] Add expect actual checker
This commit is contained in:
committed by
teamcityserver
parent
faadb08174
commit
c3060e861f
-4
@@ -38,10 +38,6 @@ FILE: RedundantModalityModifierChecker.kt
|
||||
public abstract interface Foo : R|kotlin/Any| {
|
||||
}
|
||||
public abstract expect class AbstractClass : R|Foo| {
|
||||
public expect constructor(): R|AbstractClass| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public abstract expect override fun foo(): R|kotlin/Unit|
|
||||
|
||||
public abstract expect fun bar(): R|kotlin/Unit|
|
||||
|
||||
-4
@@ -2,10 +2,6 @@ FILE: B.kt
|
||||
public abstract expect interface Other : R|kotlin/Any| {
|
||||
}
|
||||
public final expect class Another : R|kotlin/Any| {
|
||||
public expect constructor(): R|b/d/Another| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
}
|
||||
public final fun baz(): R|kotlin/Unit| {
|
||||
}
|
||||
|
||||
-4
@@ -1,10 +1,6 @@
|
||||
Module: m1-common
|
||||
FILE: common.kt
|
||||
public final expect class MyList : R|kotlin/Any| {
|
||||
public expect constructor(): R|MyList| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final expect fun get(i: R|kotlin/Int|): R|kotlin/Int|
|
||||
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ plugins {
|
||||
dependencies {
|
||||
implementation(project(":compiler:fir:tree"))
|
||||
implementation(project(":compiler:fir:tree:tree-generator"))
|
||||
implementation(project(":compiler:resolution.common"))
|
||||
implementation(project(":kotlin-reflect"))
|
||||
implementation(project(":kotlin-reflect-api"))
|
||||
|
||||
|
||||
+48
-2
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
|
||||
import org.jetbrains.kotlin.descriptors.EffectiveVisibility
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.diagnostics.WhenMissingCase
|
||||
import org.jetbrains.kotlin.fir.FirModuleData
|
||||
import org.jetbrains.kotlin.fir.PrivateForInline
|
||||
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.*
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
@@ -26,6 +27,7 @@ import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.ForbiddenNamedArgumentsTarget
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility.Incompatible
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import kotlin.properties.PropertyDelegateProvider
|
||||
import kotlin.properties.ReadOnlyProperty
|
||||
@@ -785,7 +787,6 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
||||
val ABSTRACT_PROPERTY_WITH_SETTER by error<KtPropertyAccessor>()
|
||||
val PRIVATE_SETTER_FOR_ABSTRACT_PROPERTY by error<KtModifierListOwner>(PositioningStrategy.PRIVATE_MODIFIER)
|
||||
val PRIVATE_SETTER_FOR_OPEN_PROPERTY by error<KtModifierListOwner>(PositioningStrategy.PRIVATE_MODIFIER)
|
||||
val EXPECTED_PRIVATE_DECLARATION by error<KtModifierListOwner>(PositioningStrategy.VISIBILITY_MODIFIER)
|
||||
val VAL_WITH_SETTER by error<KtPropertyAccessor>()
|
||||
val CONST_VAL_NOT_TOP_LEVEL_OR_OBJECT by error<KtElement>(PositioningStrategy.CONST_MODIFIER)
|
||||
val CONST_VAL_WITH_GETTER by error<KtElement>()
|
||||
@@ -815,11 +816,56 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
||||
|
||||
val MPP_PROJECTS by object : DiagnosticGroup("Multi-platform projects") {
|
||||
val EXPECTED_DECLARATION_WITH_BODY by error<KtDeclaration>(PositioningStrategy.DECLARATION_SIGNATURE)
|
||||
val EXPECTED_CLASS_CONSTRUCTOR_DELEGATION_CALL by error<KtConstructorDelegationCall>()
|
||||
val EXPECTED_CLASS_CONSTRUCTOR_PROPERTY_PARAMETER by error<KtParameter>()
|
||||
val EXPECTED_ENUM_CONSTRUCTOR by error<KtConstructor<*>>()
|
||||
val EXPECTED_ENUM_ENTRY_WITH_BODY by error<KtEnumEntry>()
|
||||
val EXPECTED_PROPERTY_INITIALIZER by error<KtExpression>()
|
||||
|
||||
// TODO: need to cover `by` as well as delegate expression
|
||||
val EXPECTED_DELEGATED_PROPERTY by error<KtExpression>()
|
||||
val EXPECTED_LATEINIT_PROPERTY by error<KtModifierListOwner>(PositioningStrategy.LATEINIT_MODIFIER)
|
||||
val SUPERTYPE_INITIALIZED_IN_EXPECTED_CLASS by error<PsiElement>()
|
||||
val EXPECTED_PRIVATE_DECLARATION by error<KtModifierListOwner>(PositioningStrategy.VISIBILITY_MODIFIER)
|
||||
val IMPLEMENTATION_BY_DELEGATION_IN_EXPECT_CLASS by error<KtDelegatedSuperTypeEntry>()
|
||||
|
||||
val ACTUAL_TYPE_ALIAS_NOT_TO_CLASS by error<KtTypeAlias>(PositioningStrategy.DECLARATION_SIGNATURE)
|
||||
val ACTUAL_TYPE_ALIAS_TO_CLASS_WITH_DECLARATION_SITE_VARIANCE by error<KtTypeAlias>(PositioningStrategy.DECLARATION_SIGNATURE)
|
||||
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 ACTUAL_ANNOTATION_CONFLICTING_DEFAULT_ARGUMENT_VALUE by error<PsiElement> {
|
||||
parameter<FirVariableSymbol<*>>("parameter")
|
||||
}
|
||||
|
||||
val EXPECTED_FUNCTION_SOURCE_WITH_DEFAULT_ARGUMENTS_NOT_FOUND by error<PsiElement>()
|
||||
|
||||
val NO_ACTUAL_FOR_EXPECT by error<KtNamedDeclaration>(PositioningStrategy.INCOMPATIBLE_DECLARATION) {
|
||||
parameter<Symbol>("declaration")
|
||||
parameter<FirModuleData>("module")
|
||||
parameter<Map<Incompatible<Symbol>, Collection<Symbol>>>("compatibility")
|
||||
}
|
||||
|
||||
val ACTUAL_WITHOUT_EXPECT by error<KtNamedDeclaration> {
|
||||
parameter<Symbol>("declaration")
|
||||
parameter<Map<Incompatible<Symbol>, Collection<Symbol>>>("compatibility")
|
||||
}
|
||||
|
||||
val AMBIGUOUS_ACTUALS by error<KtNamedDeclaration>(PositioningStrategy.INCOMPATIBLE_DECLARATION) {
|
||||
parameter<Symbol>("declaration")
|
||||
parameter<Collection<Symbol>>("candidates")
|
||||
}
|
||||
|
||||
val AMBIGUOUS_EXPECTS by error<KtNamedDeclaration>(PositioningStrategy.INCOMPATIBLE_DECLARATION) {
|
||||
parameter<Symbol>("declaration")
|
||||
parameter<Collection<FirModuleData>>("modules")
|
||||
}
|
||||
|
||||
val NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS by error<KtNamedDeclaration>(PositioningStrategy.ACTUAL_DECLARATION_NAME) {
|
||||
parameter<Symbol>("declaration")
|
||||
parameter<List<Pair<Symbol, Map<Incompatible<Symbol>, Collection<Symbol>>>>>("members")
|
||||
}
|
||||
|
||||
val ACTUAL_MISSING by error<KtNamedDeclaration>(PositioningStrategy.ACTUAL_DECLARATION_NAME)
|
||||
}
|
||||
|
||||
val DESTRUCTING_DECLARATION by object : DiagnosticGroup("Destructuring declaration") {
|
||||
|
||||
+2
@@ -77,6 +77,8 @@ enum class PositioningStrategy(private val strategy: String? = null) {
|
||||
DATA_MODIFIER,
|
||||
SPREAD_OPERATOR,
|
||||
DECLARATION_WITH_BODY,
|
||||
INCOMPATIBLE_DECLARATION,
|
||||
ACTUAL_DECLARATION_NAME,
|
||||
|
||||
;
|
||||
|
||||
|
||||
+26
-1
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
|
||||
import org.jetbrains.kotlin.descriptors.EffectiveVisibility
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.diagnostics.WhenMissingCase
|
||||
import org.jetbrains.kotlin.fir.FirModuleData
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.SourceElementPositioningStrategies
|
||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
@@ -40,10 +41,14 @@ import org.jetbrains.kotlin.psi.KtBinaryExpressionWithTypeRHS
|
||||
import org.jetbrains.kotlin.psi.KtCallExpression
|
||||
import org.jetbrains.kotlin.psi.KtClass
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
import org.jetbrains.kotlin.psi.KtConstructor
|
||||
import org.jetbrains.kotlin.psi.KtConstructorDelegationCall
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtDeclarationWithBody
|
||||
import org.jetbrains.kotlin.psi.KtDelegatedSuperTypeEntry
|
||||
import org.jetbrains.kotlin.psi.KtDestructuringDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtEnumEntry
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.psi.KtFunction
|
||||
import org.jetbrains.kotlin.psi.KtIfExpression
|
||||
@@ -66,6 +71,7 @@ import org.jetbrains.kotlin.psi.KtWhenCondition
|
||||
import org.jetbrains.kotlin.psi.KtWhenEntry
|
||||
import org.jetbrains.kotlin.psi.KtWhenExpression
|
||||
import org.jetbrains.kotlin.resolve.ForbiddenNamedArgumentsTarget
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility.Incompatible
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
|
||||
/*
|
||||
@@ -425,7 +431,6 @@ object FirErrors {
|
||||
val ABSTRACT_PROPERTY_WITH_SETTER by error0<KtPropertyAccessor>()
|
||||
val PRIVATE_SETTER_FOR_ABSTRACT_PROPERTY by error0<KtModifierListOwner>(SourceElementPositioningStrategies.PRIVATE_MODIFIER)
|
||||
val PRIVATE_SETTER_FOR_OPEN_PROPERTY by error0<KtModifierListOwner>(SourceElementPositioningStrategies.PRIVATE_MODIFIER)
|
||||
val EXPECTED_PRIVATE_DECLARATION by error0<KtModifierListOwner>(SourceElementPositioningStrategies.VISIBILITY_MODIFIER)
|
||||
val VAL_WITH_SETTER by error0<KtPropertyAccessor>()
|
||||
val CONST_VAL_NOT_TOP_LEVEL_OR_OBJECT by error0<KtElement>(SourceElementPositioningStrategies.CONST_MODIFIER)
|
||||
val CONST_VAL_WITH_GETTER by error0<KtElement>()
|
||||
@@ -443,9 +448,29 @@ object FirErrors {
|
||||
|
||||
// Multi-platform projects
|
||||
val EXPECTED_DECLARATION_WITH_BODY by error0<KtDeclaration>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
|
||||
val EXPECTED_CLASS_CONSTRUCTOR_DELEGATION_CALL by error0<KtConstructorDelegationCall>()
|
||||
val EXPECTED_CLASS_CONSTRUCTOR_PROPERTY_PARAMETER by error0<KtParameter>()
|
||||
val EXPECTED_ENUM_CONSTRUCTOR by error0<KtConstructor<*>>()
|
||||
val EXPECTED_ENUM_ENTRY_WITH_BODY by error0<KtEnumEntry>()
|
||||
val EXPECTED_PROPERTY_INITIALIZER by error0<KtExpression>()
|
||||
val EXPECTED_DELEGATED_PROPERTY by error0<KtExpression>()
|
||||
val EXPECTED_LATEINIT_PROPERTY by error0<KtModifierListOwner>(SourceElementPositioningStrategies.LATEINIT_MODIFIER)
|
||||
val SUPERTYPE_INITIALIZED_IN_EXPECTED_CLASS by error0<PsiElement>()
|
||||
val EXPECTED_PRIVATE_DECLARATION by error0<KtModifierListOwner>(SourceElementPositioningStrategies.VISIBILITY_MODIFIER)
|
||||
val IMPLEMENTATION_BY_DELEGATION_IN_EXPECT_CLASS by error0<KtDelegatedSuperTypeEntry>()
|
||||
val ACTUAL_TYPE_ALIAS_NOT_TO_CLASS by error0<KtTypeAlias>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
|
||||
val ACTUAL_TYPE_ALIAS_TO_CLASS_WITH_DECLARATION_SITE_VARIANCE by error0<KtTypeAlias>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
|
||||
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 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<Incompatible<FirBasedSymbol<*>>, Collection<FirBasedSymbol<*>>>>(SourceElementPositioningStrategies.INCOMPATIBLE_DECLARATION)
|
||||
val ACTUAL_WITHOUT_EXPECT by error2<KtNamedDeclaration, FirBasedSymbol<*>, Map<Incompatible<FirBasedSymbol<*>>, Collection<FirBasedSymbol<*>>>>()
|
||||
val AMBIGUOUS_ACTUALS by error2<KtNamedDeclaration, FirBasedSymbol<*>, Collection<FirBasedSymbol<*>>>(SourceElementPositioningStrategies.INCOMPATIBLE_DECLARATION)
|
||||
val AMBIGUOUS_EXPECTS by error2<KtNamedDeclaration, FirBasedSymbol<*>, Collection<FirModuleData>>(SourceElementPositioningStrategies.INCOMPATIBLE_DECLARATION)
|
||||
val NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS by error2<KtNamedDeclaration, FirBasedSymbol<*>, List<Pair<FirBasedSymbol<*>, Map<Incompatible<FirBasedSymbol<*>>, Collection<FirBasedSymbol<*>>>>>>(SourceElementPositioningStrategies.ACTUAL_DECLARATION_NAME)
|
||||
val ACTUAL_MISSING by error0<KtNamedDeclaration>(SourceElementPositioningStrategies.ACTUAL_DECLARATION_NAME)
|
||||
|
||||
// Destructuring declaration
|
||||
val INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION by error0<KtDestructuringDeclaration>()
|
||||
|
||||
+1
@@ -30,6 +30,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
|
||||
FirInfixFunctionDeclarationChecker,
|
||||
FirExposedVisibilityDeclarationChecker,
|
||||
FirCyclicTypeBoundsChecker,
|
||||
FirExpectActualDeclarationChecker
|
||||
)
|
||||
|
||||
override val functionCheckers: Set<FirFunctionChecker>
|
||||
|
||||
+242
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
* 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.fir.analysis.checkers.declaration
|
||||
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isActual
|
||||
import org.jetbrains.kotlin.fir.languageVersionSettings
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
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.types.coneType
|
||||
import org.jetbrains.kotlin.fir.types.toSymbol
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility.*
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||
|
||||
@Suppress("DuplicatedCode")
|
||||
object FirExpectActualDeclarationChecker : FirBasicDeclarationChecker() {
|
||||
override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
if (!context.session.languageVersionSettings.supportsFeature(LanguageFeature.MultiPlatformProjects)) return
|
||||
if (declaration !is FirMemberDeclaration) return
|
||||
if (declaration.isActual) {
|
||||
checkActualDeclarationHasExpected(declaration, context, reporter)
|
||||
}
|
||||
}
|
||||
|
||||
private fun <T> checkActualDeclarationHasExpected(
|
||||
declaration: T,
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter,
|
||||
checkActual: Boolean = true
|
||||
) where T : FirDeclaration, T : FirMemberDeclaration {
|
||||
val scopeSession = ScopeSession()
|
||||
val symbol = declaration.symbol
|
||||
val compatibilityToMembersMap = FirExpectActualResolver.findExpectForActual(symbol, context.session, scopeSession) ?: return
|
||||
val session = context.session
|
||||
|
||||
checkAmbiguousExpects(symbol, compatibilityToMembersMap, symbol, context, reporter)
|
||||
|
||||
val source = declaration.source
|
||||
if (!declaration.isActual) {
|
||||
if (compatibilityToMembersMap.allStrongIncompatibilities()) return
|
||||
|
||||
if (Compatible in compatibilityToMembersMap) {
|
||||
if (checkActual && requireActualModifier(symbol, session)) {
|
||||
reporter.reportOn(source, FirErrors.ACTUAL_MISSING, context)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
val singleIncompatibility = compatibilityToMembersMap.keys.singleOrNull()
|
||||
when {
|
||||
singleIncompatibility is Incompatible.ClassScopes -> {
|
||||
assert(symbol is FirRegularClassSymbol || symbol is FirTypeAliasSymbol) {
|
||||
"Incompatible.ClassScopes is only possible for a class or a typealias: $declaration"
|
||||
}
|
||||
|
||||
// Do not report "expected members have no actual ones" for those expected members, for which there's a clear
|
||||
// (albeit maybe incompatible) single actual suspect, declared in the actual class.
|
||||
// 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<FirBasedSymbol<*>, Map<Incompatible<FirBasedSymbol<*>>, Collection<FirBasedSymbol<*>>>>
|
||||
): Boolean {
|
||||
val (expectedMember, incompatibility) = expectedWithIncompatibility
|
||||
val actualMember = incompatibility.values.singleOrNull()?.singleOrNull()
|
||||
return actualMember != null &&
|
||||
actualMember.isExplicitActualDeclaration() &&
|
||||
!incompatibility.allStrongIncompatibilities() &&
|
||||
FirExpectActualResolver.findExpectForActual(
|
||||
actualMember,
|
||||
session,
|
||||
scopeSession
|
||||
)?.values?.singleOrNull()?.singleOrNull() == expectedMember
|
||||
}
|
||||
|
||||
val nonTrivialUnfulfilled = singleIncompatibility.unfulfilled.filterNot(::hasSingleActualSuspect)
|
||||
|
||||
if (nonTrivialUnfulfilled.isNotEmpty()) {
|
||||
reporter.reportOn(source, FirErrors.NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS, symbol, nonTrivialUnfulfilled, context)
|
||||
}
|
||||
}
|
||||
|
||||
Compatible !in compatibilityToMembersMap -> {
|
||||
reporter.reportOn(source, FirErrors.ACTUAL_WITHOUT_EXPECT, symbol, compatibilityToMembersMap.cast(), context)
|
||||
}
|
||||
|
||||
else -> {
|
||||
val expected = compatibilityToMembersMap[Compatible]!!.first()
|
||||
if (expected is FirRegularClassSymbol && expected.classKind == ClassKind.ANNOTATION_CLASS) {
|
||||
val klass = symbol.expandedClass(session)
|
||||
val actualConstructor = klass?.declarationSymbols?.firstIsInstanceOrNull<FirConstructorSymbol>()
|
||||
val expectedConstructor = expected.declarationSymbols.firstIsInstanceOrNull<FirConstructorSymbol>()
|
||||
if (expectedConstructor != null && actualConstructor != null) {
|
||||
checkAnnotationConstructors(source, expectedConstructor, actualConstructor, context, reporter)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
private fun checkAnnotationConstructors(
|
||||
source: FirSourceElement?,
|
||||
expected: FirConstructorSymbol,
|
||||
actual: FirConstructorSymbol,
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter
|
||||
) {
|
||||
for (expectedValueParameter in expected.valueParameterSymbols) {
|
||||
// Actual parameter with the same name is guaranteed to exist because this method is only called for compatible annotations
|
||||
val actualValueDescriptor = actual.valueParameterSymbols.first { it.name == expectedValueParameter.name }
|
||||
|
||||
if (expectedValueParameter.hasDefaultValue && actualValueDescriptor.hasDefaultValue) {
|
||||
// TODO
|
||||
// val expectedParameter =
|
||||
// DescriptorToSourceUtils.descriptorToDeclaration(expectedValueParameter) as? KtParameter ?: continue
|
||||
//
|
||||
// val expectedValue = trace.bindingContext.get(BindingContext.COMPILE_TIME_VALUE, expectedParameter.defaultValue)
|
||||
// ?.toConstantValue(expectedValueParameter.type)
|
||||
//
|
||||
// val actualValue =
|
||||
// getActualAnnotationParameterValue(actualValueDescriptor, trace.bindingContext, expectedValueParameter.type)
|
||||
// if (expectedValue != actualValue) {
|
||||
// val ktParameter = DescriptorToSourceUtils.descriptorToDeclaration(actualValueDescriptor)
|
||||
// val target = (ktParameter as? KtParameter)?.defaultValue ?: (reportOn as? KtTypeAlias)?.nameIdentifier ?: reportOn
|
||||
// trace.report(Errors.ACTUAL_ANNOTATION_CONFLICTING_DEFAULT_ARGUMENT_VALUE.on(target, actualValueDescriptor))
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun checkAmbiguousExpects(
|
||||
actualDeclaration: FirBasedSymbol<*>,
|
||||
compatibility: Map<ExpectActualCompatibility<FirBasedSymbol<*>>, List<FirBasedSymbol<*>>>,
|
||||
symbol: FirBasedSymbol<*>,
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter
|
||||
) {
|
||||
val filesWithAtLeastWeaklyCompatibleExpects = compatibility.asSequence()
|
||||
.filter { (compatibility, _) ->
|
||||
compatibility.isCompatibleOrWeakCompatible()
|
||||
}
|
||||
.map { (_, members) -> members }
|
||||
.flatten()
|
||||
.map { it.moduleData }
|
||||
.sortedBy { it.name.asString() }
|
||||
.toList()
|
||||
|
||||
if (filesWithAtLeastWeaklyCompatibleExpects.size > 1) {
|
||||
reporter.reportOn(
|
||||
actualDeclaration.source,
|
||||
FirErrors.AMBIGUOUS_EXPECTS,
|
||||
symbol,
|
||||
filesWithAtLeastWeaklyCompatibleExpects,
|
||||
context
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun Map<out ExpectActualCompatibility<*>, *>.allStrongIncompatibilities(): Boolean {
|
||||
return keys.all { it is Incompatible && it.kind == IncompatibilityKind.STRONG }
|
||||
}
|
||||
|
||||
private fun ExpectActualCompatibility<FirBasedSymbol<*>>.isCompatibleOrWeakCompatible(): Boolean {
|
||||
return this is Compatible ||
|
||||
this is Incompatible && kind == IncompatibilityKind.WEAK
|
||||
}
|
||||
|
||||
// we don't require `actual` modifier on
|
||||
// - annotation constructors, because annotation classes can only have one constructor
|
||||
// - inline class primary constructors, because inline class must have primary constructor
|
||||
// - value parameter inside primary constructor of inline class, because inline class must have one value parameter
|
||||
private fun requireActualModifier(declaration: FirBasedSymbol<*>, session: FirSession): Boolean {
|
||||
return !declaration.isAnnotationConstructor(session) &&
|
||||
!declaration.isPrimaryConstructorOfInlineClass(session) &&
|
||||
!isUnderlyingPropertyOfInlineClass(declaration)
|
||||
}
|
||||
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
private fun isUnderlyingPropertyOfInlineClass(declaration: FirBasedSymbol<*>): Boolean {
|
||||
// TODO
|
||||
// return declaration is PropertyDescriptor && declaration.isUnderlyingPropertyOfInlineClass()
|
||||
return false
|
||||
}
|
||||
|
||||
private fun FirBasedSymbol<*>.isExplicitActualDeclaration(): Boolean {
|
||||
// return when (this) {
|
||||
// is FirConstructor -> DescriptorToSourceUtils.getSourceFromDescriptor(this) is KtConstructor<*>
|
||||
// is FirCallableMemberDeclaration<*> -> kind == CallableMemberDescriptor.Kind.DECLARATION
|
||||
// else -> true
|
||||
// }
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
fun FirBasedSymbol<*>.isAnnotationConstructor(session: FirSession): Boolean {
|
||||
if (this !is FirConstructorSymbol) return false
|
||||
return getConstructedClass(session)?.classKind == ClassKind.ANNOTATION_CLASS
|
||||
}
|
||||
|
||||
fun FirBasedSymbol<*>.isEnumConstructor(session: FirSession): Boolean {
|
||||
if (this !is FirConstructorSymbol) return false
|
||||
return getConstructedClass(session)?.classKind == ClassKind.ENUM_CLASS
|
||||
}
|
||||
|
||||
fun FirBasedSymbol<*>.isPrimaryConstructorOfInlineClass(session: FirSession): Boolean {
|
||||
if (this !is FirConstructorSymbol) return false
|
||||
return getConstructedClass(session)?.isInlineOrValueClass() == true && this.isPrimary
|
||||
}
|
||||
|
||||
fun FirConstructorSymbol.getConstructedClass(session: FirSession): FirRegularClassSymbol? {
|
||||
return resolvedReturnTypeRef.coneType
|
||||
.fullyExpandedType(session)
|
||||
.toSymbol(session) as? FirRegularClassSymbol?
|
||||
}
|
||||
|
||||
fun FirBasedSymbol<*>.expandedClass(session: FirSession): FirRegularClassSymbol? {
|
||||
return when (this) {
|
||||
is FirTypeAliasSymbol -> resolvedExpandedTypeRef.coneType.fullyExpandedType(session).toSymbol(session) as? FirRegularClassSymbol
|
||||
is FirRegularClassSymbol -> this
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
+658
@@ -0,0 +1,658 @@
|
||||
/*
|
||||
* 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.fir.analysis.checkers.declaration
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.collectEnumEntries
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.fullyExpandedClass
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.*
|
||||
import org.jetbrains.kotlin.fir.resolve.*
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutorByMap
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.chain
|
||||
import org.jetbrains.kotlin.fir.scopes.*
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirPackageMemberScope
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeClassifierLookupTag
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility
|
||||
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
||||
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
|
||||
import org.jetbrains.kotlin.utils.SmartList
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import org.jetbrains.kotlin.utils.keysToMap
|
||||
|
||||
object FirExpectActualResolver {
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
fun findExpectForActual(
|
||||
actualSymbol: FirBasedSymbol<*>,
|
||||
useSiteSession: FirSession,
|
||||
scopeSession: ScopeSession
|
||||
): Map<ExpectActualCompatibility<FirBasedSymbol<*>>, List<FirBasedSymbol<*>>>? {
|
||||
return when (actualSymbol) {
|
||||
is FirCallableSymbol<*> -> {
|
||||
val callableId = actualSymbol.callableId
|
||||
val classId = callableId.classId
|
||||
var parentSubstitutor: ConeSubstitutor? = null
|
||||
var expectContainingClass: FirRegularClassSymbol? = null
|
||||
var actualContainingClass: FirRegularClassSymbol? = null
|
||||
val candidates = when {
|
||||
classId != null -> {
|
||||
expectContainingClass = useSiteSession.dependenciesSymbolProvider.getClassLikeSymbolByFqName(classId)?.let {
|
||||
it.fullyExpandedClass(it.moduleData.session)
|
||||
}
|
||||
actualContainingClass = useSiteSession.symbolProvider.getClassLikeSymbolByFqName(classId)
|
||||
?.fullyExpandedClass(useSiteSession)
|
||||
|
||||
val expectTypeParameters = expectContainingClass?.typeParameterSymbols.orEmpty()
|
||||
val actualTypeParameters = actualContainingClass
|
||||
?.typeParameterSymbols
|
||||
.orEmpty()
|
||||
parentSubstitutor = createTypeParameterSubstitutor(expectTypeParameters, actualTypeParameters, useSiteSession)
|
||||
when (actualSymbol) {
|
||||
is FirConstructorSymbol -> expectContainingClass?.getConstructors(scopeSession)
|
||||
else -> expectContainingClass?.getMembers(callableId.callableName, scopeSession)
|
||||
}.orEmpty()
|
||||
}
|
||||
callableId.isLocal -> return null
|
||||
else -> {
|
||||
val scope = FirPackageMemberScope(callableId.packageName, useSiteSession, useSiteSession.dependenciesSymbolProvider)
|
||||
mutableListOf<FirCallableSymbol<*>>().apply {
|
||||
scope.processFunctionsByName(callableId.callableName) { add(it) }
|
||||
scope.processPropertiesByName(callableId.callableName) { add(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
candidates.filter { expectSymbol ->
|
||||
actualSymbol != expectSymbol && expectSymbol.isExpect
|
||||
}.groupBy { expectDeclaration ->
|
||||
areCompatibleCallables(
|
||||
expectDeclaration,
|
||||
actualSymbol,
|
||||
useSiteSession,
|
||||
parentSubstitutor,
|
||||
expectContainingClass,
|
||||
actualContainingClass
|
||||
)
|
||||
}
|
||||
}
|
||||
is FirClassLikeSymbol<*> -> {
|
||||
val expectClassSymbol = useSiteSession.dependenciesSymbolProvider
|
||||
.getClassLikeSymbolByFqName(actualSymbol.classId) as? FirRegularClassSymbol ?: return null
|
||||
val compatibility = areCompatibleClassifiers(expectClassSymbol, actualSymbol, useSiteSession, scopeSession)
|
||||
mapOf(compatibility to listOf(expectClassSymbol))
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
private fun areCompatibleClassifiers(
|
||||
expectClassSymbol: FirRegularClassSymbol,
|
||||
actualClassLikeSymbol: FirClassLikeSymbol<*>,
|
||||
actualSession: FirSession,
|
||||
scopeSession: ScopeSession
|
||||
): ExpectActualCompatibility<FirBasedSymbol<*>> {
|
||||
// Can't check FQ names here because nested expected class may be implemented via actual typealias's expansion with the other FQ name
|
||||
assert(expectClassSymbol.classId.shortClassName == actualClassLikeSymbol.classId.shortClassName) {
|
||||
"This function should be invoked only for declarations with the same name: $expectClassSymbol, $actualClassLikeSymbol"
|
||||
}
|
||||
|
||||
val actualClass = when (actualClassLikeSymbol) {
|
||||
is FirRegularClassSymbol -> actualClassLikeSymbol
|
||||
is FirTypeAliasSymbol -> actualClassLikeSymbol.resolvedExpandedTypeRef.coneType.fullyExpandedType(actualSession)
|
||||
.toSymbol(actualSession) as? FirRegularClassSymbol
|
||||
?: return ExpectActualCompatibility.Compatible // do not report extra error on erroneous typealias
|
||||
else -> throw IllegalArgumentException("Incorrect actual classifier for $expectClassSymbol: $actualClassLikeSymbol")
|
||||
}
|
||||
|
||||
if (expectClassSymbol.classKind != actualClass.classKind) return ExpectActualCompatibility.Incompatible.ClassKind
|
||||
|
||||
if (!equalBy(expectClassSymbol, actualClass) { listOf(it.isCompanion, it.isInner, it.isInline /*|| it.isValue*/) }) {
|
||||
return ExpectActualCompatibility.Incompatible.ClassModifiers
|
||||
}
|
||||
|
||||
val expectTypeParameterSymbols = expectClassSymbol.typeParameterSymbols
|
||||
val actualTypeParameterSymbols = actualClass.typeParameterSymbols
|
||||
if (expectTypeParameterSymbols.size != actualTypeParameterSymbols.size) {
|
||||
return ExpectActualCompatibility.Incompatible.TypeParameterCount
|
||||
}
|
||||
|
||||
if (!areCompatibleModalities(expectClassSymbol.modality, actualClass.modality)) {
|
||||
return ExpectActualCompatibility.Incompatible.Modality
|
||||
}
|
||||
|
||||
if (expectClassSymbol.visibility != actualClass.visibility) {
|
||||
return ExpectActualCompatibility.Incompatible.Visibility
|
||||
}
|
||||
|
||||
val substitutor = createTypeParameterSubstitutor(expectTypeParameterSymbols, actualTypeParameterSymbols, actualSession)
|
||||
|
||||
val expectSession = expectClassSymbol.moduleData.session
|
||||
areCompatibleTypeParameters(expectTypeParameterSymbols, actualTypeParameterSymbols, actualSession, expectSession, substitutor).let {
|
||||
if (it != ExpectActualCompatibility.Compatible) {
|
||||
return it
|
||||
}
|
||||
}
|
||||
|
||||
// Subtract kotlin.Any from supertypes because it's implicitly added if no explicit supertype is specified,
|
||||
// and not added if an explicit supertype _is_ specified
|
||||
val expectSupertypes = expectClassSymbol.superConeTypes.filterNot { it.classId == actualSession.builtinTypes.anyType.id }
|
||||
val actualSupertypes = actualClass.superConeTypes.filterNot { it.classId == actualSession.builtinTypes.anyType.id }
|
||||
if (
|
||||
expectSupertypes.map(substitutor::substituteOrSelf).any { expectSupertype ->
|
||||
actualSupertypes.none { actualSupertype ->
|
||||
areCompatibleTypes(expectSupertype, actualSupertype, expectSession, actualSession)
|
||||
}
|
||||
}
|
||||
) {
|
||||
return ExpectActualCompatibility.Incompatible.Supertypes
|
||||
}
|
||||
|
||||
areCompatibleClassScopes(expectClassSymbol, actualClass, actualSession, scopeSession, substitutor).let {
|
||||
if (it != ExpectActualCompatibility.Compatible) {
|
||||
return it
|
||||
}
|
||||
}
|
||||
|
||||
return ExpectActualCompatibility.Compatible
|
||||
}
|
||||
|
||||
private fun areCompatibleClassScopes(
|
||||
expectClassSymbol: FirRegularClassSymbol,
|
||||
actualClassSymbol: FirRegularClassSymbol,
|
||||
actualSession: FirSession,
|
||||
scopeSession: ScopeSession,
|
||||
substitutor: ConeSubstitutor
|
||||
): ExpectActualCompatibility<FirBasedSymbol<*>> {
|
||||
val unfulfilled =
|
||||
mutableListOf<Pair<FirBasedSymbol<*>, Map<ExpectActualCompatibility.Incompatible<FirBasedSymbol<*>>, MutableCollection<FirBasedSymbol<*>>>>>()
|
||||
|
||||
val allActualMembers = actualClassSymbol.getMembers(scopeSession, actualSession)
|
||||
val actualMembersByName = allActualMembers.groupBy { it.name }
|
||||
val actualConstructors = allActualMembers.filterIsInstance<FirConstructorSymbol>()
|
||||
|
||||
outer@ for (expectMember in expectClassSymbol.getMembers(scopeSession)) {
|
||||
// if (expectMember is CallableMemberDescriptor && !expectMember.kind.isReal) continue
|
||||
|
||||
val actualMembers = when (expectMember) {
|
||||
is FirConstructorSymbol -> actualConstructors
|
||||
else -> actualMembersByName[expectMember.name]?.filter { actualMember ->
|
||||
expectMember is FirRegularClassSymbol && actualMember is FirRegularClassSymbol ||
|
||||
expectMember is FirCallableSymbol<*> && actualMember is FirCallableSymbol<*>
|
||||
}.orEmpty()
|
||||
}
|
||||
|
||||
val mapping = actualMembers.keysToMap { actualMember ->
|
||||
when (expectMember) {
|
||||
is FirCallableSymbol<*> ->
|
||||
areCompatibleCallables(
|
||||
expectMember,
|
||||
actualMember as FirCallableSymbol<*>,
|
||||
actualSession,
|
||||
substitutor,
|
||||
expectClassSymbol,
|
||||
actualClassSymbol
|
||||
)
|
||||
is FirRegularClassSymbol ->
|
||||
areCompatibleClassifiers(expectMember, actualMember as FirRegularClassSymbol, actualSession, scopeSession)
|
||||
else -> throw UnsupportedOperationException("Unsupported declaration: $expectMember ($actualMembers)")
|
||||
}
|
||||
}
|
||||
if (mapping.values.any { it == ExpectActualCompatibility.Compatible }) continue
|
||||
|
||||
val incompatibilityMap =
|
||||
mutableMapOf<ExpectActualCompatibility.Incompatible<FirBasedSymbol<*>>, MutableCollection<FirBasedSymbol<*>>>()
|
||||
for ((declaration, compatibility) in mapping) {
|
||||
when (compatibility) {
|
||||
ExpectActualCompatibility.Compatible -> continue@outer
|
||||
is ExpectActualCompatibility.Incompatible -> incompatibilityMap.getOrPut(compatibility) { SmartList() }.add(declaration)
|
||||
}
|
||||
}
|
||||
|
||||
unfulfilled.add(expectMember to incompatibilityMap)
|
||||
}
|
||||
|
||||
if (expectClassSymbol.classKind == ClassKind.ENUM_CLASS) {
|
||||
val expectEntries = expectClassSymbol.collectEnumEntries().map { it.name }
|
||||
val actualEntries = actualClassSymbol.collectEnumEntries().map { it.name }
|
||||
|
||||
if (!actualEntries.containsAll(expectEntries)) {
|
||||
return ExpectActualCompatibility.Incompatible.EnumEntries
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: check static scope?
|
||||
|
||||
if (unfulfilled.isEmpty()) return ExpectActualCompatibility.Compatible
|
||||
|
||||
return ExpectActualCompatibility.Incompatible.ClassScopes(unfulfilled)
|
||||
}
|
||||
|
||||
private fun areCompatibleCallables(
|
||||
expectDeclaration: FirCallableSymbol<*>,
|
||||
actualDeclaration: FirCallableSymbol<*>,
|
||||
actualSession: FirSession,
|
||||
parentSubstitutor: ConeSubstitutor?,
|
||||
expectContainingClass: FirRegularClassSymbol?,
|
||||
actualContainingClass: FirRegularClassSymbol?,
|
||||
): ExpectActualCompatibility<FirBasedSymbol<*>> {
|
||||
assert(
|
||||
(expectDeclaration is FirConstructorSymbol && actualDeclaration is FirConstructorSymbol) ||
|
||||
expectDeclaration.callableId.callableName == actualDeclaration.callableId.callableName
|
||||
) {
|
||||
"This function should be invoked only for declarations with the same name: $expectDeclaration, $actualDeclaration"
|
||||
}
|
||||
assert((expectDeclaration.dispatchReceiverType == null) == (actualDeclaration.dispatchReceiverType == null)) {
|
||||
"This function should be invoked only for declarations in the same kind of container (both members or both top level): $expectDeclaration, $actualDeclaration"
|
||||
}
|
||||
|
||||
val expectSession = expectDeclaration.moduleData.session
|
||||
|
||||
if (
|
||||
expectDeclaration is FirConstructorSymbol &&
|
||||
actualDeclaration is FirConstructorSymbol &&
|
||||
expectContainingClass?.classKind == ClassKind.ENUM_CLASS &&
|
||||
actualContainingClass?.classKind == ClassKind.ENUM_CLASS
|
||||
) {
|
||||
return ExpectActualCompatibility.Compatible
|
||||
}
|
||||
|
||||
if (expectDeclaration is FirNamedFunctionSymbol != actualDeclaration is FirNamedFunctionSymbol) {
|
||||
return ExpectActualCompatibility.Incompatible.CallableKind
|
||||
}
|
||||
|
||||
val expectedReceiverType = expectDeclaration.resolvedReceiverTypeRef
|
||||
val actualReceiverType = actualDeclaration.resolvedReceiverTypeRef
|
||||
if ((expectedReceiverType != null) != (actualReceiverType != null)) {
|
||||
return ExpectActualCompatibility.Incompatible.ParameterShape
|
||||
}
|
||||
|
||||
val expectedValueParameters = expectDeclaration.valueParameterSymbols
|
||||
val actualValueParameters = actualDeclaration.valueParameterSymbols
|
||||
if (!valueParametersCountCompatible(expectDeclaration, actualDeclaration, expectedValueParameters, actualValueParameters)) {
|
||||
return ExpectActualCompatibility.Incompatible.ParameterCount
|
||||
}
|
||||
|
||||
val expectedTypeParameters = expectDeclaration.typeParameterSymbols
|
||||
val actualTypeParameters = actualDeclaration.typeParameterSymbols
|
||||
if (expectedTypeParameters.size != actualTypeParameters.size) {
|
||||
return ExpectActualCompatibility.Incompatible.TypeParameterCount
|
||||
}
|
||||
|
||||
val substitutor = createTypeParameterSubstitutor(expectedTypeParameters, actualTypeParameters, actualSession, parentSubstitutor)
|
||||
|
||||
if (
|
||||
!areCompatibleTypeLists(
|
||||
expectedValueParameters.toTypeList(substitutor),
|
||||
actualValueParameters.toTypeList(ConeSubstitutor.Empty),
|
||||
expectSession,
|
||||
actualSession
|
||||
) ||
|
||||
!areCompatibleTypes(
|
||||
expectedReceiverType?.coneType?.let { substitutor.substituteOrSelf(it) },
|
||||
actualReceiverType?.coneType,
|
||||
expectSession,
|
||||
actualSession
|
||||
)
|
||||
) {
|
||||
return ExpectActualCompatibility.Incompatible.ParameterTypes
|
||||
}
|
||||
if (
|
||||
!areCompatibleTypes(
|
||||
substitutor.substituteOrSelf(expectDeclaration.resolvedReturnTypeRef.coneType),
|
||||
actualDeclaration.resolvedReturnTypeRef.coneType,
|
||||
expectSession,
|
||||
actualSession
|
||||
)
|
||||
) {
|
||||
return ExpectActualCompatibility.Incompatible.ReturnType
|
||||
}
|
||||
|
||||
// TODO: implement hasStableParameterNames calculation
|
||||
// if (actualDeclaration.hasStableParameterNames() && !equalsBy(expectedValueParameters, actualValueParameters, ValueParameterDescriptor::getName)) return Incompatible.ParameterNames
|
||||
|
||||
if (!equalsBy(expectedTypeParameters, actualTypeParameters) { it.name }) {
|
||||
return ExpectActualCompatibility.Incompatible.TypeParameterNames
|
||||
}
|
||||
|
||||
if (
|
||||
!areCompatibleModalities(
|
||||
expectDeclaration.modality,
|
||||
actualDeclaration.modality,
|
||||
(expectDeclaration.dispatchReceiverType?.toSymbol(expectSession) as? FirRegularClassSymbol)?.modality,
|
||||
actualContainingClass?.modality
|
||||
)
|
||||
) {
|
||||
return ExpectActualCompatibility.Incompatible.Modality
|
||||
}
|
||||
|
||||
if (!areDeclarationsWithCompatibleVisibilities(expectDeclaration.resolvedStatus, actualDeclaration.resolvedStatus)) {
|
||||
return ExpectActualCompatibility.Incompatible.Visibility
|
||||
}
|
||||
|
||||
areCompatibleTypeParameters(expectedTypeParameters, actualTypeParameters, actualSession, expectSession, substitutor).let {
|
||||
if (it != ExpectActualCompatibility.Compatible) {
|
||||
return it
|
||||
}
|
||||
}
|
||||
|
||||
if (!equalsBy(expectedValueParameters, actualValueParameters) { it.isVararg }) {
|
||||
return ExpectActualCompatibility.Incompatible.ValueParameterVararg
|
||||
}
|
||||
|
||||
// Adding noinline/crossinline to parameters is disallowed, except if the expected declaration was not inline at all
|
||||
if (expectDeclaration is FirNamedFunctionSymbol && expectDeclaration.isInline) {
|
||||
if (expectedValueParameters.indices.any { i -> !expectedValueParameters[i].isNoinline && actualValueParameters[i].isNoinline }) {
|
||||
return ExpectActualCompatibility.Incompatible.ValueParameterNoinline
|
||||
}
|
||||
if (expectedValueParameters.indices.any { i -> !expectedValueParameters[i].isCrossinline && actualValueParameters[i].isCrossinline }) {
|
||||
return ExpectActualCompatibility.Incompatible.ValueParameterCrossinline
|
||||
}
|
||||
}
|
||||
|
||||
when {
|
||||
expectDeclaration is FirNamedFunctionSymbol && actualDeclaration is FirNamedFunctionSymbol -> areCompatibleFunctions(
|
||||
expectDeclaration,
|
||||
actualDeclaration
|
||||
).let { if (it != ExpectActualCompatibility.Compatible) return it }
|
||||
|
||||
expectDeclaration is FirConstructorSymbol && actualDeclaration is FirConstructorSymbol -> areCompatibleFunctions(
|
||||
expectDeclaration,
|
||||
actualDeclaration
|
||||
).let { if (it != ExpectActualCompatibility.Compatible) return it }
|
||||
|
||||
expectDeclaration is FirPropertySymbol && actualDeclaration is FirPropertySymbol -> areCompatibleProperties(
|
||||
expectDeclaration,
|
||||
actualDeclaration
|
||||
).let { if (it != ExpectActualCompatibility.Compatible) return it }
|
||||
|
||||
else -> throw AssertionError("Unsupported declarations: $expectDeclaration, $actualDeclaration")
|
||||
}
|
||||
|
||||
return ExpectActualCompatibility.Compatible
|
||||
}
|
||||
|
||||
private fun createTypeParameterSubstitutor(
|
||||
expectedTypeParameters: List<FirTypeParameterSymbol>,
|
||||
actualTypeParameters: List<FirTypeParameterSymbol>,
|
||||
useSiteSession: FirSession,
|
||||
parentSubstitutor: ConeSubstitutor? = null
|
||||
): ConeSubstitutor {
|
||||
val substitution = expectedTypeParameters.zip(actualTypeParameters).associate { (expectedParameterSymbol, actualParameterSymbol) ->
|
||||
expectedParameterSymbol to actualParameterSymbol.toLookupTag().constructType(emptyArray(), isNullable = false)
|
||||
}
|
||||
val substitutor = ConeSubstitutorByMap(
|
||||
substitution,
|
||||
useSiteSession
|
||||
)
|
||||
if (parentSubstitutor == null) {
|
||||
return substitutor
|
||||
}
|
||||
return substitutor.chain(parentSubstitutor)
|
||||
}
|
||||
|
||||
private fun valueParametersCountCompatible(
|
||||
expectDeclaration: FirCallableSymbol<*>,
|
||||
actualDeclaration: FirCallableSymbol<*>,
|
||||
expectValueParameters: List<FirValueParameterSymbol>,
|
||||
actualValueParameters: List<FirValueParameterSymbol>
|
||||
): Boolean {
|
||||
if (expectValueParameters.size == actualValueParameters.size) return true
|
||||
|
||||
return if (
|
||||
expectDeclaration.isAnnotationConstructor(expectDeclaration.moduleData.session) &&
|
||||
actualDeclaration.isAnnotationConstructor(actualDeclaration.moduleData.session)
|
||||
) {
|
||||
expectValueParameters.isEmpty() && actualValueParameters.all { it.hasDefaultValue }
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
private fun areCompatibleTypeLists(
|
||||
expectedTypes: List<ConeKotlinType?>,
|
||||
actualTypes: List<ConeKotlinType?>,
|
||||
expectSession: FirSession,
|
||||
actualSession: FirSession
|
||||
): Boolean {
|
||||
for (i in expectedTypes.indices) {
|
||||
if (!areCompatibleTypes(expectedTypes[i], actualTypes[i], expectSession, actualSession)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun areCompatibleTypes(
|
||||
expectedType: ConeKotlinType?,
|
||||
actualType: ConeKotlinType?,
|
||||
expectSession: FirSession,
|
||||
actualSession: FirSession
|
||||
): Boolean {
|
||||
if (expectedType == null) return actualType == null
|
||||
if (actualType == null) return false
|
||||
|
||||
val typeCheckerContext = ConeInferenceContextForExpectActual(expectSession, actualSession).newBaseTypeCheckerContext(
|
||||
errorTypesEqualToAnything = false,
|
||||
stubTypesEqualToAnything = true
|
||||
)
|
||||
return AbstractTypeChecker.equalTypes(
|
||||
typeCheckerContext,
|
||||
expectedType,
|
||||
actualType
|
||||
)
|
||||
}
|
||||
|
||||
private fun areCompatibleModalities(
|
||||
expectModality: Modality?,
|
||||
actualModality: Modality?,
|
||||
expectContainingClassModality: Modality? = null,
|
||||
actualContainingClassModality: Modality? = null
|
||||
): Boolean {
|
||||
val result = (expectModality == actualModality) ||
|
||||
(expectModality == Modality.FINAL && (actualModality == Modality.OPEN || actualModality == Modality.ABSTRACT))
|
||||
if (result) return true
|
||||
if (expectContainingClassModality == null || actualContainingClassModality == null) return result
|
||||
return expectModality == expectContainingClassModality && actualModality == actualContainingClassModality
|
||||
}
|
||||
|
||||
private fun areDeclarationsWithCompatibleVisibilities(
|
||||
expectStatus: FirDeclarationStatus,
|
||||
actualStatus: FirDeclarationStatus
|
||||
): Boolean {
|
||||
val compare = Visibilities.compare(expectStatus.visibility, actualStatus.visibility)
|
||||
return if (expectStatus.modality != Modality.FINAL) {
|
||||
// For overridable declarations visibility should match precisely, see KT-19664
|
||||
compare == 0
|
||||
} else {
|
||||
// For non-overridable declarations actuals are allowed to have more permissive visibility
|
||||
compare != null && compare <= 0
|
||||
}
|
||||
}
|
||||
|
||||
private fun areCompatibleTypeParameters(
|
||||
expectTypeParameterSymbols: List<FirTypeParameterSymbol>,
|
||||
actualTypeParameterSymbols: List<FirTypeParameterSymbol>,
|
||||
actualSession: FirSession,
|
||||
expectSession: FirSession,
|
||||
substitutor: ConeSubstitutor
|
||||
): ExpectActualCompatibility<FirBasedSymbol<*>> {
|
||||
for (i in expectTypeParameterSymbols.indices) {
|
||||
val expectBounds = expectTypeParameterSymbols[i].resolvedBounds.map { it.coneType }
|
||||
val actualBounds = actualTypeParameterSymbols[i].resolvedBounds.map { it.coneType }
|
||||
if (
|
||||
expectBounds.size != actualBounds.size ||
|
||||
!areCompatibleTypeLists(expectBounds.map(substitutor::substituteOrSelf), actualBounds, expectSession, actualSession)
|
||||
) {
|
||||
return ExpectActualCompatibility.Incompatible.TypeParameterUpperBounds
|
||||
}
|
||||
}
|
||||
|
||||
if (!equalsBy(expectTypeParameterSymbols, actualTypeParameterSymbols) { it.variance }) {
|
||||
return ExpectActualCompatibility.Incompatible.TypeParameterVariance
|
||||
}
|
||||
|
||||
// Removing "reified" from an expected function's type parameter is fine
|
||||
if (
|
||||
expectTypeParameterSymbols.indices.any { i ->
|
||||
!expectTypeParameterSymbols[i].isReified && actualTypeParameterSymbols[i].isReified
|
||||
}
|
||||
) {
|
||||
return ExpectActualCompatibility.Incompatible.TypeParameterReified
|
||||
}
|
||||
|
||||
return ExpectActualCompatibility.Compatible
|
||||
}
|
||||
|
||||
private fun areCompatibleFunctions(
|
||||
expectFunction: FirCallableSymbol<*>,
|
||||
actualFunction: FirCallableSymbol<*>
|
||||
): ExpectActualCompatibility<FirBasedSymbol<*>> {
|
||||
if (!equalBy(expectFunction, actualFunction) { f -> f.isSuspend }) {
|
||||
return ExpectActualCompatibility.Incompatible.FunctionModifiersDifferent
|
||||
}
|
||||
|
||||
if (
|
||||
expectFunction.isExternal && !actualFunction.isExternal ||
|
||||
expectFunction.isInfix && !actualFunction.isInfix ||
|
||||
expectFunction.isInline && !actualFunction.isInline ||
|
||||
expectFunction.isOperator && !actualFunction.isOperator ||
|
||||
expectFunction.isTailRec && !actualFunction.isTailRec
|
||||
) {
|
||||
return ExpectActualCompatibility.Incompatible.FunctionModifiersNotSubset
|
||||
}
|
||||
|
||||
return ExpectActualCompatibility.Compatible
|
||||
}
|
||||
|
||||
private fun areCompatibleProperties(a: FirPropertySymbol, b: FirPropertySymbol): ExpectActualCompatibility<FirBasedSymbol<*>> {
|
||||
if (!equalBy(a, b) { p -> p.isVar }) {
|
||||
return ExpectActualCompatibility.Incompatible.PropertyKind
|
||||
}
|
||||
if (!equalBy(a, b) { p -> listOf(p.isConst, p.isLateInit) }) {
|
||||
return ExpectActualCompatibility.Incompatible.PropertyModifiers
|
||||
}
|
||||
return ExpectActualCompatibility.Compatible
|
||||
}
|
||||
|
||||
// ---------------------------------------- Utils ----------------------------------------
|
||||
|
||||
private class ConeInferenceContextForExpectActual(val expectSession: FirSession, val actualSession: FirSession) : ConeInferenceContext {
|
||||
override val session: FirSession
|
||||
get() = actualSession
|
||||
|
||||
override fun areEqualTypeConstructors(c1: TypeConstructorMarker, c2: TypeConstructorMarker): Boolean {
|
||||
if (c1 !is ConeClassifierLookupTag || c2 !is ConeClassifierLookupTag) {
|
||||
return c1 == c2
|
||||
}
|
||||
return isExpectedClassAndActualTypeAlias(c1, c2) ||
|
||||
isExpectedClassAndActualTypeAlias(c2, c1) ||
|
||||
c1 == c2
|
||||
}
|
||||
|
||||
// For example, expectedTypeConstructor may be the expected class kotlin.text.StringBuilder, while actualTypeConstructor
|
||||
// is java.lang.StringBuilder. For the purposes of type compatibility checking, we must consider these types equal here.
|
||||
// Note that the case of an "actual class" works as expected though, because the actual class by definition has the same FQ name
|
||||
// as the corresponding expected class, so their type constructors are equal as per AbstractClassTypeConstructor#equals
|
||||
private fun isExpectedClassAndActualTypeAlias(
|
||||
expectLookupTag: ConeClassifierLookupTag,
|
||||
actualLookupTag: ConeClassifierLookupTag
|
||||
): Boolean {
|
||||
val expectDeclaration = expectLookupTag.toClassLikeDeclaration(expectSession) ?: return false
|
||||
val actualDeclaration = actualLookupTag.toClassLikeDeclaration(actualSession) ?: return false
|
||||
|
||||
if (!expectDeclaration.isExpect) return false
|
||||
val expectClassId = when (expectDeclaration) {
|
||||
is FirRegularClassSymbol -> expectDeclaration.classId
|
||||
is FirTypeAliasSymbol -> expectDeclaration.resolvedExpandedTypeRef.coneType.classId
|
||||
else -> null
|
||||
} ?: return false
|
||||
return expectClassId == actualDeclaration.classId
|
||||
}
|
||||
|
||||
private fun ConeClassifierLookupTag.toClassLikeDeclaration(session: FirSession): FirClassLikeSymbol<*>? {
|
||||
return this.toSymbol(session) as? FirClassLikeSymbol<*>
|
||||
}
|
||||
}
|
||||
|
||||
private fun List<FirValueParameterSymbol>.toTypeList(substitutor: ConeSubstitutor): List<ConeKotlinType> {
|
||||
return this.map { substitutor.substituteOrSelf(it.resolvedReturnTypeRef.coneType) }
|
||||
}
|
||||
|
||||
private val FirCallableSymbol<*>.valueParameterSymbols: List<FirValueParameterSymbol>
|
||||
get() = (this as? FirFunctionSymbol<*>)?.valueParameterSymbols ?: emptyList()
|
||||
|
||||
private inline fun <T, K> equalsBy(first: List<T>, second: List<T>, selector: (T) -> K): Boolean {
|
||||
for (i in first.indices) {
|
||||
if (selector(first[i]) != selector(second[i])) return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private inline fun <T, K> equalBy(first: T, second: T, selector: (T) -> K): Boolean =
|
||||
selector(first) == selector(second)
|
||||
|
||||
private fun FirClassSymbol<*>.getMembers(
|
||||
scopeSession: ScopeSession,
|
||||
session: FirSession = moduleData.session
|
||||
): Collection<FirBasedSymbol<*>> {
|
||||
val scope = defaultType().scope(useSiteSession = session, scopeSession, FakeOverrideTypeCalculator.DoNothing)
|
||||
?: return emptyList()
|
||||
return mutableListOf<FirBasedSymbol<*>>().apply {
|
||||
for (name in scope.getCallableNames()) {
|
||||
scope.getMembersTo(this, name)
|
||||
}
|
||||
for (name in declarationSymbols.mapNotNull { (it as? FirRegularClassSymbol)?.classId?.shortClassName }) {
|
||||
addIfNotNull(scope.getSingleClassifier(name) as? FirRegularClassSymbol)
|
||||
}
|
||||
getConstructorsTo(this, scope)
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirClassSymbol<*>.getConstructors(
|
||||
scopeSession: ScopeSession,
|
||||
session: FirSession = moduleData.session
|
||||
): Collection<FirConstructorSymbol> {
|
||||
return mutableListOf<FirConstructorSymbol>().apply {
|
||||
getConstructorsTo(this, unsubstitutedScope(session, scopeSession, withForcedTypeCalculator = false))
|
||||
}
|
||||
}
|
||||
|
||||
private fun getConstructorsTo(destination: MutableList<in FirConstructorSymbol>, scope: FirTypeScope) {
|
||||
scope.getDeclaredConstructors().mapTo(destination) { it }
|
||||
}
|
||||
|
||||
private fun FirClassSymbol<*>.getMembers(name: Name, scopeSession: ScopeSession): Collection<FirCallableSymbol<*>> {
|
||||
val scope = defaultType().scope(useSiteSession = moduleData.session, scopeSession, FakeOverrideTypeCalculator.DoNothing)
|
||||
?: return emptyList()
|
||||
return mutableListOf<FirCallableSymbol<*>>().apply {
|
||||
scope.getMembersTo(this, name)
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
private fun FirTypeScope.getMembersTo(
|
||||
destination: MutableList<in FirCallableSymbol<*>>,
|
||||
name: Name,
|
||||
) {
|
||||
processFunctionsByName(name) { destination.add(it) }
|
||||
processPropertiesByName(name) { destination.add(it) }
|
||||
}
|
||||
|
||||
private val FirBasedSymbol<*>.name: Name
|
||||
get() = when (this) {
|
||||
is FirCallableSymbol<*> -> name
|
||||
is FirRegularClassSymbol -> classId.shortClassName
|
||||
else -> error("Should not be here")
|
||||
}
|
||||
}
|
||||
+42
-1
@@ -13,6 +13,8 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.AMBI
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.DECLARATION_NAME
|
||||
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.COLLECTION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.MODULE_DATA
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.FUNCTION_PARAMETERS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.NOT_RENDERED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.NULLABLE_STRING
|
||||
@@ -38,6 +40,16 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_PROPERTY
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_PROPERTY_WITH_SETTER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_SUPER_CALL
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ACCESSOR_FOR_DELEGATED_PROPERTY
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ACTUAL_ANNOTATION_CONFLICTING_DEFAULT_ARGUMENT_VALUE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ACTUAL_MISSING
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ACTUAL_TYPE_ALIAS_NOT_TO_CLASS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ACTUAL_TYPE_ALIAS_TO_CLASS_WITH_DECLARATION_SITE_VARIANCE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ACTUAL_TYPE_ALIAS_WITH_COMPLEX_SUBSTITUTION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ACTUAL_TYPE_ALIAS_WITH_USE_SITE_VARIANCE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ACTUAL_WITHOUT_EXPECT
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.AMBIGUOUS_ACTUALS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.AMBIGUOUS_EXPECTS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ANNOTATION_ARGUMENT_MUST_BE_CONST
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ANNOTATION_CLASS_CONSTRUCTOR_CALL
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ANNOTATION_CLASS_MEMBER
|
||||
@@ -124,9 +136,14 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EQUALITY_NOT_APPL
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ERROR_FROM_JAVA_RESOLUTION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ERROR_IN_CONTRACT_DESCRIPTION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPANDED_TYPE_CANNOT_BE_INHERITED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPECTED_CLASS_CONSTRUCTOR_DELEGATION_CALL
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPECTED_CLASS_CONSTRUCTOR_PROPERTY_PARAMETER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPECTED_CONDITION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPECTED_DECLARATION_WITH_BODY
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPECTED_DELEGATED_PROPERTY
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPECTED_ENUM_CONSTRUCTOR
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPECTED_ENUM_ENTRY_WITH_BODY
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPECTED_FUNCTION_SOURCE_WITH_DEFAULT_ARGUMENTS_NOT_FOUND
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPECTED_LATEINIT_PROPERTY
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPECTED_PRIVATE_DECLARATION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPECTED_PROPERTY_INITIALIZER
|
||||
@@ -171,6 +188,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ILLEGAL_CONST_EXP
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ILLEGAL_KOTLIN_VERSION_STRING_VALUE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ILLEGAL_SELECTOR
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ILLEGAL_UNDERSCORE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.IMPLEMENTATION_BY_DELEGATION_IN_EXPECT_CLASS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INAPPLICABLE_CANDIDATE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INAPPLICABLE_FILE_TARGET
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INAPPLICABLE_INFIX_MODIFIER
|
||||
@@ -244,6 +262,8 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_A_LOOP_LABEL
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_A_SUPERTYPE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_NULL_ASSERTION_ON_CALLABLE_REFERENCE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_NULL_ASSERTION_ON_LAMBDA_EXPRESSION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_ACTUAL_FOR_EXPECT
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_COMPANION_OBJECT
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_ELSE_IN_WHEN
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_GET_METHOD
|
||||
@@ -321,6 +341,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SPREAD_OF_NULLABL
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUPERCLASS_NOT_ACCESSIBLE_FROM_INTERFACE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUPERTYPES_FOR_ANNOTATION_CLASS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUPERTYPE_APPEARS_TWICE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUPERTYPE_INITIALIZED_IN_EXPECTED_CLASS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUPERTYPE_INITIALIZED_IN_INTERFACE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUPERTYPE_INITIALIZED_WITHOUT_PRIMARY_CONSTRUCTOR
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUPERTYPE_IS_EXTENSION_FUNCTION_TYPE
|
||||
@@ -1134,10 +1155,30 @@ class FirDefaultErrorMessages {
|
||||
|
||||
// Multi-platform projects
|
||||
map.put(EXPECTED_DECLARATION_WITH_BODY, "Expected declaration must not have a body")
|
||||
map.put(EXPECTED_CLASS_CONSTRUCTOR_DELEGATION_CALL, "Explicit delegation call for constructor of an expected class is not allowed")
|
||||
map.put(EXPECTED_CLASS_CONSTRUCTOR_PROPERTY_PARAMETER, "Expected class constructor cannot have a property parameter")
|
||||
map.put(EXPECTED_ENUM_CONSTRUCTOR, "Expected enum class cannot have a constructor")
|
||||
map.put(EXPECTED_ENUM_ENTRY_WITH_BODY, "Expected enum entry cannot have a body")
|
||||
map.put(EXPECTED_PROPERTY_INITIALIZER, "Expected property cannot have an initializer")
|
||||
map.put(EXPECTED_DELEGATED_PROPERTY, "Expected property cannot be delegated")
|
||||
map.put(EXPECTED_PRIVATE_DECLARATION, "Expected declaration cannot be private")
|
||||
map.put(EXPECTED_LATEINIT_PROPERTY, "Expected property cannot be lateinit")
|
||||
map.put(EXPECTED_PRIVATE_DECLARATION, "Expected declaration cannot be private")
|
||||
map.put(SUPERTYPE_INITIALIZED_IN_EXPECTED_CLASS, "Expected classes cannot initialize supertypes")
|
||||
map.put(EXPECTED_PRIVATE_DECLARATION, "Expected declaration cannot be private")
|
||||
map.put(IMPLEMENTATION_BY_DELEGATION_IN_EXPECT_CLASS, "Implementation by delegation in expected classes is prohibited")
|
||||
map.put(ACTUAL_TYPE_ALIAS_NOT_TO_CLASS, "Right-hand side of actual type alias should be a class, not another type alias")
|
||||
map.put(ACTUAL_TYPE_ALIAS_TO_CLASS_WITH_DECLARATION_SITE_VARIANCE, "Aliased class should not have type parameters with declaration-site variance")
|
||||
map.put(ACTUAL_TYPE_ALIAS_WITH_USE_SITE_VARIANCE, "Right-hand side of actual type alias cannot contain use-site variance or star projections")
|
||||
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", SYMBOL)
|
||||
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. Please add the corresponding file to compilation sources")
|
||||
map.put(NO_ACTUAL_FOR_EXPECT, "Expected {0} has no actual declaration in module {1}{2}", SYMBOL, MODULE_DATA, FirPlatformIncompatibilityDiagnosticRenderer.TEXT)
|
||||
map.put(ACTUAL_WITHOUT_EXPECT, "{0} has no corresponding expected declaration{1}", SYMBOL, FirPlatformIncompatibilityDiagnosticRenderer.TEXT)
|
||||
map.put(AMBIGUOUS_ACTUALS, "{0} has several compatible actual declarations in modules {1}", SYMBOL, SYMBOLS)
|
||||
map.put(AMBIGUOUS_EXPECTS, "{0} has several compatible expect declarations in modules {1}", SYMBOL, COLLECTION(MODULE_DATA))
|
||||
map.put(NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS, "Actual class ''{0}'' has no corresponding members for expected class members:{1}", SYMBOL, FirIncompatibleExpectedActualClassScopesRenderer.TEXT)
|
||||
map.put(ACTUAL_MISSING, "Declaration must be marked with 'actual'")
|
||||
|
||||
// Destructuring declaration
|
||||
map.put(INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION, "Initializer required for destructuring declaration")
|
||||
|
||||
+16
-5
@@ -8,8 +8,10 @@ package org.jetbrains.kotlin.fir.analysis.diagnostics
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.diagnostics.WhenMissingCase
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.ContextIndependentParameterRenderer
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.Renderer
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirModuleData
|
||||
import org.jetbrains.kotlin.fir.FirRenderer
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.*
|
||||
@@ -34,11 +36,7 @@ object FirDiagnosticRenderers {
|
||||
}
|
||||
}
|
||||
|
||||
val SYMBOLS = Renderer { symbols: Collection<FirBasedSymbol<*>> ->
|
||||
symbols.joinToString(prefix = "[", postfix = "]", separator = ", ", limit = 3, truncated = "...") { symbol ->
|
||||
SYMBOL.render(symbol)
|
||||
}
|
||||
}
|
||||
val SYMBOLS = COLLECTION(SYMBOL)
|
||||
|
||||
val RENDER_COLLECTION_OF_TYPES = Renderer { types: Collection<ConeKotlinType> ->
|
||||
types.joinToString(separator = ", ") { type ->
|
||||
@@ -133,4 +131,17 @@ object FirDiagnosticRenderers {
|
||||
}
|
||||
|
||||
val FUNCTION_PARAMETERS = Renderer { hasValueParameters: Boolean -> if (hasValueParameters) "..." else "" }
|
||||
|
||||
val MODULE_DATA = Renderer<FirModuleData> {
|
||||
"Module ${it.name}"
|
||||
}
|
||||
|
||||
@Suppress("FunctionName")
|
||||
fun <T> COLLECTION(renderer: ContextIndependentParameterRenderer<T>): ContextIndependentParameterRenderer<Collection<T>> {
|
||||
return Renderer { list ->
|
||||
list.joinToString(prefix = "[", postfix = "]", separator = ", ", limit = 3, truncated = "...") {
|
||||
renderer.render(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.diagnostics
|
||||
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.ContextIndependentParameterRenderer
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility.Incompatible
|
||||
|
||||
class FirPlatformIncompatibilityDiagnosticRenderer(
|
||||
private val mode: MultiplatformDiagnosticRenderingMode
|
||||
) : ContextIndependentParameterRenderer<Map<Incompatible<FirBasedSymbol<*>>, Collection<FirBasedSymbol<*>>>> {
|
||||
override fun render(
|
||||
obj: Map<Incompatible<FirBasedSymbol<*>>, Collection<FirBasedSymbol<*>>>,
|
||||
): String {
|
||||
if (obj.isEmpty()) return ""
|
||||
|
||||
return buildString {
|
||||
mode.newLine(this)
|
||||
renderIncompatibilityInformation(obj, "", mode)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmField
|
||||
val TEXT = FirPlatformIncompatibilityDiagnosticRenderer(MultiplatformDiagnosticRenderingMode())
|
||||
}
|
||||
}
|
||||
|
||||
class FirIncompatibleExpectedActualClassScopesRenderer(
|
||||
private val mode: MultiplatformDiagnosticRenderingMode
|
||||
) : ContextIndependentParameterRenderer<List<Pair<FirBasedSymbol<*>, Map<Incompatible<FirBasedSymbol<*>>, Collection<FirBasedSymbol<*>>>>>> {
|
||||
override fun render(
|
||||
obj: List<Pair<FirBasedSymbol<*>, Map<Incompatible<FirBasedSymbol<*>>, Collection<FirBasedSymbol<*>>>>>
|
||||
): String {
|
||||
if (obj.isEmpty()) return ""
|
||||
|
||||
return buildString {
|
||||
mode.newLine(this)
|
||||
renderIncompatibleClassScopes(obj, "", mode)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmField
|
||||
val TEXT = FirIncompatibleExpectedActualClassScopesRenderer(MultiplatformDiagnosticRenderingMode())
|
||||
}
|
||||
}
|
||||
|
||||
open class MultiplatformDiagnosticRenderingMode {
|
||||
open fun newLine(sb: StringBuilder) {
|
||||
sb.appendLine()
|
||||
}
|
||||
|
||||
open fun renderList(sb: StringBuilder, elements: List<() -> Unit>) {
|
||||
sb.appendLine()
|
||||
for (element in elements) {
|
||||
element()
|
||||
}
|
||||
}
|
||||
|
||||
open fun renderSymbol(sb: StringBuilder, symbol: FirBasedSymbol<*>, indent: String) {
|
||||
sb.append(indent)
|
||||
sb.append(INDENTATION_UNIT)
|
||||
sb.appendLine(FirDiagnosticRenderers.SYMBOL.render(symbol))
|
||||
}
|
||||
}
|
||||
|
||||
private fun StringBuilder.renderIncompatibilityInformation(
|
||||
map: Map<Incompatible<FirBasedSymbol<*>>, Collection<FirBasedSymbol<*>>>,
|
||||
indent: String,
|
||||
mode: MultiplatformDiagnosticRenderingMode
|
||||
) {
|
||||
for ((incompatibility, descriptors) in map) {
|
||||
append(indent)
|
||||
append("The following declaration")
|
||||
if (descriptors.size == 1) append(" is") else append("s are")
|
||||
append(" incompatible")
|
||||
incompatibility.reason?.let { append(" because $it") }
|
||||
append(":")
|
||||
|
||||
mode.renderList(this, descriptors.map { descriptor ->
|
||||
{ mode.renderSymbol(this, descriptor, indent) }
|
||||
})
|
||||
|
||||
if (incompatibility is Incompatible.ClassScopes) {
|
||||
append(indent)
|
||||
append("No actual members are found for expected members listed below:")
|
||||
mode.newLine(this)
|
||||
renderIncompatibleClassScopes(incompatibility.unfulfilled, indent, mode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun StringBuilder.renderIncompatibleClassScopes(
|
||||
unfulfilled: List<Pair<FirBasedSymbol<*>, Map<Incompatible<FirBasedSymbol<*>>, Collection<FirBasedSymbol<*>>>>>,
|
||||
indent: String,
|
||||
mode: MultiplatformDiagnosticRenderingMode
|
||||
) {
|
||||
mode.renderList(this, unfulfilled.indices.map { index ->
|
||||
{
|
||||
val (descriptor, mapping) = unfulfilled[index]
|
||||
mode.renderSymbol(this, descriptor, indent)
|
||||
if (mapping.isNotEmpty()) {
|
||||
mode.newLine(this)
|
||||
renderIncompatibilityInformation(mapping, indent + INDENTATION_UNIT, mode)
|
||||
}
|
||||
if (index != unfulfilled.lastIndex) {
|
||||
mode.newLine(this)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private const val INDENTATION_UNIT = " "
|
||||
+4
@@ -272,4 +272,8 @@ object SourceElementPositioningStrategies {
|
||||
LightTreePositioningStrategies.DECLARATION_WITH_BODY,
|
||||
PositioningStrategies.DECLARATION_WITH_BODY
|
||||
)
|
||||
|
||||
// TODO
|
||||
val ACTUAL_DECLARATION_NAME = DEFAULT
|
||||
val INCOMPATIBLE_DECLARATION = DEFAULT
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.fir.scopes.impl.FirStandardOverrideChecker
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirTypeIntersectionScope
|
||||
import org.jetbrains.kotlin.fir.scopes.scopeForClass
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.fir.typeContext
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
@@ -95,6 +96,7 @@ private fun ConeKotlinType.scope(useSiteSession: FirSession, scopeSession: Scope
|
||||
}
|
||||
}
|
||||
|
||||
fun FirClassSymbol<*>.defaultType(): ConeClassLikeType = fir.defaultType()
|
||||
|
||||
fun FirClass.defaultType(): ConeClassLikeType =
|
||||
when (this) {
|
||||
|
||||
+6
-2
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.fir.scopes.impl
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.symbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.ensureResolvedForCalls
|
||||
@@ -19,8 +20,11 @@ import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.utils.SmartList
|
||||
|
||||
class FirPackageMemberScope(val fqName: FqName, val session: FirSession) : FirScope() {
|
||||
private val symbolProvider = session.symbolProvider
|
||||
class FirPackageMemberScope(
|
||||
val fqName: FqName,
|
||||
val session: FirSession,
|
||||
private val symbolProvider: FirSymbolProvider = session.symbolProvider
|
||||
) : FirScope() {
|
||||
private val classifierCache: MutableMap<Name, FirClassifierSymbol<*>?> = mutableMapOf()
|
||||
private val functionCache: MutableMap<Name, List<FirNamedFunctionSymbol>> = mutableMapOf()
|
||||
private val propertyCache: MutableMap<Name, List<FirPropertySymbol>> = mutableMapOf()
|
||||
|
||||
+14
@@ -107,6 +107,20 @@ inline val FirClassLikeSymbol<*>.isLocal: Boolean get() = classId.isLocal
|
||||
inline val FirClassSymbol<*>.isLocalClassOrAnonymousObject: Boolean
|
||||
get() = classId.isLocal || this is FirAnonymousObjectSymbol
|
||||
|
||||
inline val FirClassLikeSymbol<*>.isExpect: Boolean
|
||||
get() = when (this) {
|
||||
is FirRegularClassSymbol -> isExpect
|
||||
is FirTypeAliasSymbol -> isExpect
|
||||
else -> false
|
||||
}
|
||||
|
||||
inline val FirClassLikeSymbol<*>.isActual: Boolean
|
||||
get() = when (this) {
|
||||
is FirRegularClassSymbol -> isActual
|
||||
is FirTypeAliasSymbol -> isActual
|
||||
else -> false
|
||||
}
|
||||
|
||||
inline val FirClassSymbol<*>.isInterface: Boolean
|
||||
get() = classKind.isInterface
|
||||
|
||||
|
||||
@@ -568,4 +568,10 @@ abstract class AbstractTypeApproximator(
|
||||
|
||||
// Nothing or Nothing!
|
||||
private fun KotlinTypeMarker.isTrivialSub() = lowerBoundIfFlexible().isNothing()
|
||||
|
||||
override fun CapturedTypeMarker.typeParameter(): TypeParameterMarker? {
|
||||
with(ctx) {
|
||||
return typeParameter()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ class MyImpl2: My {
|
||||
expect interface Outer {
|
||||
interface Inner {
|
||||
open fun bar()
|
||||
open fun bas() {}
|
||||
<!EXPECTED_DECLARATION_WITH_BODY!>open fun bas()<!> {}
|
||||
<!REDUNDANT_MODIFIER!>open<!> abstract fun bat(): Int
|
||||
fun foo()
|
||||
}
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
expect enum class En {
|
||||
E1,
|
||||
E2 {
|
||||
fun foo() = ""
|
||||
<!EXPECTED_DECLARATION_WITH_BODY!>fun foo()<!> = ""
|
||||
},
|
||||
E3 { };
|
||||
}
|
||||
|
||||
+2
-2
@@ -16,10 +16,10 @@ expect interface My {
|
||||
// FILE: jvm.kt
|
||||
actual interface My {
|
||||
actual fun openFunPositive() = Unit
|
||||
actual fun openFunNegative()
|
||||
<!ACTUAL_WITHOUT_EXPECT!>actual fun openFunNegative()<!>
|
||||
actual fun abstractFun()
|
||||
|
||||
actual val openValPositive: Int get() = 0
|
||||
actual val openValNegative: Int
|
||||
<!ACTUAL_WITHOUT_EXPECT!>actual val openValNegative: Int<!>
|
||||
actual val abstractVal: Int
|
||||
}
|
||||
|
||||
+2
-2
@@ -10,7 +10,7 @@ expect annotation class Foo5()
|
||||
expect annotation class Foo6()
|
||||
expect annotation class Foo7()
|
||||
|
||||
@Foo1
|
||||
@<!UNRESOLVED_REFERENCE!>Foo1<!>
|
||||
fun foo() {}
|
||||
|
||||
@Foo5
|
||||
@@ -45,4 +45,4 @@ actual annotation class Foo5
|
||||
|
||||
actual annotation class Foo6(val s: String = "value")
|
||||
|
||||
actual typealias Foo7 = Bar2
|
||||
<!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>actual typealias Foo7 = Bar2<!>
|
||||
|
||||
+3
-3
@@ -34,9 +34,9 @@ actual class Foo1(val s: String)
|
||||
actual class Foo2(val p: String = "value", i: Int)
|
||||
actual typealias Foo3 = JavaFoo
|
||||
|
||||
actual class Bar1(val s: String)
|
||||
actual class Bar2(val p: String = "value", i: Int)
|
||||
actual typealias Bar3 = JavaBar
|
||||
<!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>actual class Bar1(val s: String)<!>
|
||||
<!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>actual class Bar2(val p: String = "value", i: Int)<!>
|
||||
<!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>actual typealias Bar3 = JavaBar<!>
|
||||
actual class Bar4(val s: String) {
|
||||
constructor() : this("")
|
||||
}
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
|
||||
expect open class A
|
||||
expect class B : A
|
||||
open class C : <!SUPERTYPE_NOT_INITIALIZED!>A<!>
|
||||
<!UNRESOLVED_REFERENCE!>open class C : <!SUPERTYPE_NOT_INITIALIZED!>A<!><!>
|
||||
|
||||
// MODULE: m1-jvm()()(m1-common)
|
||||
// FILE: jvm.kt
|
||||
|
||||
Vendored
+1
-1
@@ -10,7 +10,7 @@ expect class FooBar {
|
||||
}
|
||||
|
||||
fun test() {
|
||||
Foo()
|
||||
<!UNRESOLVED_REFERENCE!>Foo<!>()
|
||||
Bar()
|
||||
Baz()
|
||||
FooBar()
|
||||
|
||||
+2
-2
@@ -23,11 +23,11 @@ fun foo1(x: String) {}
|
||||
fun foo2(x: Int, y: Int) {}
|
||||
fun foo2(x: String) {}
|
||||
|
||||
actual fun foo3(): String = ""
|
||||
<!ACTUAL_WITHOUT_EXPECT!>actual fun foo3(): String = ""<!>
|
||||
fun foo4(x: Int): String = ""
|
||||
|
||||
actual class NoArgConstructor {
|
||||
actual constructor()
|
||||
actual constructor(x: Int)
|
||||
<!ACTUAL_WITHOUT_EXPECT!>actual constructor(x: Int)<!>
|
||||
constructor(x: String)
|
||||
}
|
||||
|
||||
+3
-3
@@ -17,12 +17,12 @@ expect open class Foo3
|
||||
// FILE: jvm.kt
|
||||
|
||||
interface Foo1
|
||||
actual interface Foo2
|
||||
<!ACTUAL_WITHOUT_EXPECT!>actual interface Foo2<!>
|
||||
|
||||
actual var s: String = "value"
|
||||
<!ACTUAL_WITHOUT_EXPECT!>actual var s: String = "value"<!>
|
||||
|
||||
fun foo2(): Int = 0
|
||||
|
||||
<!REDECLARATION!>actual class Foo3<!>
|
||||
<!ACTUAL_WITHOUT_EXPECT, REDECLARATION!>actual class Foo3<!>
|
||||
|
||||
<!REDECLARATION!>class Foo3<!>
|
||||
|
||||
+4
-4
@@ -31,9 +31,9 @@ actual open class Container {
|
||||
actual fun protectedFun1() {} // OK: protected -> public
|
||||
actual protected fun protectedFun2() {} // OK: protected -> protected
|
||||
|
||||
actual internal fun protectedFun3() {} // BAD: protected -> internal
|
||||
actual protected fun internalFun3() {} // BAD: internal -> protected
|
||||
<!ACTUAL_WITHOUT_EXPECT!>actual internal fun protectedFun3() {}<!> // BAD: protected -> internal
|
||||
<!ACTUAL_WITHOUT_EXPECT!>actual protected fun internalFun3() {}<!> // BAD: internal -> protected
|
||||
|
||||
actual open fun openInternalFun() {} // BAD: internal+open -> public
|
||||
actual internal fun openPublicFun() {} // BAD: open+public -> internal
|
||||
<!ACTUAL_WITHOUT_EXPECT!>actual open fun openInternalFun() {}<!> // BAD: internal+open -> public
|
||||
<!ACTUAL_WITHOUT_EXPECT!>actual internal fun openPublicFun() {}<!> // BAD: open+public -> internal
|
||||
}
|
||||
|
||||
Vendored
+2
-2
@@ -4,7 +4,7 @@
|
||||
|
||||
expect class B {
|
||||
class N {
|
||||
fun body() {}
|
||||
<!EXPECTED_DECLARATION_WITH_BODY!>fun body()<!> {}
|
||||
expect fun extraHeader()
|
||||
}
|
||||
}
|
||||
@@ -39,7 +39,7 @@ actual class C {
|
||||
actual inner class I
|
||||
}
|
||||
|
||||
actual class D
|
||||
<!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>actual class D<!>
|
||||
|
||||
actual class E {
|
||||
class N
|
||||
|
||||
+2
-2
@@ -8,13 +8,13 @@ interface J
|
||||
|
||||
expect class Foo : I, C, J
|
||||
|
||||
expect class Bar : C()
|
||||
<!SUPERTYPE_INITIALIZED_WITHOUT_PRIMARY_CONSTRUCTOR!>expect class Bar : C()<!>
|
||||
|
||||
// MODULE: m2-jvm()()(m1-common)
|
||||
// FILE: jvm.kt
|
||||
actual class Foo : I, C(), J
|
||||
|
||||
actual class Bar
|
||||
<!ACTUAL_WITHOUT_EXPECT!>actual class Bar<!>
|
||||
|
||||
// MODULE: m3-js()()(m1-common)
|
||||
// FILE: js.kt
|
||||
|
||||
+2
-2
@@ -13,10 +13,10 @@ expect sealed class SealedWithPlatformActuals : SealedWithSharedActual
|
||||
package foo
|
||||
|
||||
actual sealed class SealedWithSharedActual
|
||||
class SimpleShared : SealedWithPlatformActuals()
|
||||
class SimpleShared : <!UNRESOLVED_REFERENCE!>SealedWithPlatformActuals<!>()
|
||||
|
||||
// MODULE: main()()(intermediate)
|
||||
// TARGET_PLATFORM: JVM
|
||||
package foo
|
||||
|
||||
actual sealed class SealedWithPlatformActuals <!NON_PRIVATE_OR_PROTECTED_CONSTRUCTOR_IN_SEALED!>actual constructor()<!>: SealedWithSharedActual()
|
||||
actual sealed class SealedWithPlatformActuals <!ACTUAL_WITHOUT_EXPECT, NON_PRIVATE_OR_PROTECTED_CONSTRUCTOR_IN_SEALED!>actual constructor()<!>: SealedWithSharedActual()
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
// !LANGUAGE: +MultiPlatformProjects
|
||||
// !DIAGNOSTICS: -UNSUPPORTED
|
||||
// MODULE: m1-common
|
||||
// FILE: common.kt
|
||||
|
||||
expect class Foo {
|
||||
constructor(p: Any)
|
||||
|
||||
fun f1(s: String): Int
|
||||
|
||||
fun f2(s: List<String>?): MutableMap<Boolean?, Foo>
|
||||
|
||||
fun <T : Set<Number>> f3(t: T): T?
|
||||
}
|
||||
|
||||
// MODULE: m2-js()()(m1-common)
|
||||
// FILE: js.kt
|
||||
|
||||
// TODO: do not suppress UNSUPPORTED once JS files in multi-platform tests are analyzed with JS analyzer facade
|
||||
|
||||
<!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>actual class Foo {
|
||||
<!ACTUAL_WITHOUT_EXPECT!>actual constructor(p: dynamic) {}<!>
|
||||
|
||||
<!ACTUAL_WITHOUT_EXPECT!>actual fun f1(s: dynamic): dynamic = null!!<!>
|
||||
|
||||
<!ACTUAL_WITHOUT_EXPECT!>actual fun f2(s: dynamic): MutableMap<Boolean?, Foo> = null!!<!>
|
||||
|
||||
<!ACTUAL_WITHOUT_EXPECT!>actual fun <T : Set<Number>> f3(t: T): dynamic = null!!<!>
|
||||
}<!>
|
||||
@@ -1,4 +1,3 @@
|
||||
// FIR_IDENTICAL
|
||||
// !LANGUAGE: +MultiPlatformProjects
|
||||
// !DIAGNOSTICS: -UNSUPPORTED
|
||||
// MODULE: m1-common
|
||||
|
||||
Vendored
+3
-3
@@ -20,9 +20,9 @@ expect inline class NonInlineActual(val x: Int)
|
||||
actual inline class Foo1(val x: Int) {
|
||||
actual fun bar(): String = "Hello"
|
||||
}
|
||||
actual inline class Foo2(val x: String)
|
||||
<!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>actual inline class Foo2(val x: String)<!>
|
||||
actual <!ABSENCE_OF_PRIMARY_CONSTRUCTOR_FOR_INLINE_CLASS!>inline<!> class Foo3
|
||||
|
||||
actual inline class NonInlineExpect(val x: Int)
|
||||
<!ACTUAL_WITHOUT_EXPECT!>actual inline class NonInlineExpect(val x: Int)<!>
|
||||
|
||||
actual class NonInlineActual actual constructor(actual val x: Int)
|
||||
<!ACTUAL_WITHOUT_EXPECT!>actual class NonInlineActual actual constructor(actual val x: Int)<!>
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ fun foo() {
|
||||
// MODULE: m2-jvm
|
||||
// FILE: jvm.kt
|
||||
|
||||
class Outer actual constructor() {
|
||||
class Outer <!ACTUAL_WITHOUT_EXPECT!>actual constructor()<!> {
|
||||
actual class Nested
|
||||
|
||||
actual init {}
|
||||
|
||||
+2
-2
@@ -9,10 +9,10 @@ expect fun foo()
|
||||
// FILE: jvm.kt
|
||||
package jvm
|
||||
|
||||
actual fun foo() {}
|
||||
<!ACTUAL_WITHOUT_EXPECT!>actual fun foo() {}<!>
|
||||
|
||||
// MODULE: m3-js()()(m1-common)
|
||||
// FILE: js.kt
|
||||
package js
|
||||
|
||||
actual fun foo() {}
|
||||
<!ACTUAL_WITHOUT_EXPECT!>actual fun foo() {}<!>
|
||||
|
||||
Vendored
+1
-1
@@ -9,4 +9,4 @@ expect fun foo()
|
||||
|
||||
<!NON_MEMBER_FUNCTION_NO_BODY!>actual fun foo()<!>
|
||||
|
||||
<!NON_MEMBER_FUNCTION_NO_BODY!>actual fun bar()<!>
|
||||
<!ACTUAL_WITHOUT_EXPECT, NON_MEMBER_FUNCTION_NO_BODY!>actual fun bar()<!>
|
||||
|
||||
+1
-1
@@ -2,4 +2,4 @@
|
||||
// MODULE: m1-jvm
|
||||
// FILE: jvm.kt
|
||||
|
||||
actual fun foo() { }
|
||||
<!ACTUAL_WITHOUT_EXPECT!>actual fun foo() { }<!>
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ expect fun nonInlineFun()
|
||||
// MODULE: m2-jvm()()(m1-common)
|
||||
// FILE: jvm.kt
|
||||
|
||||
actual fun inlineFun() { }
|
||||
<!ACTUAL_WITHOUT_EXPECT!>actual fun inlineFun() { }<!>
|
||||
actual fun nonInlineFun() { }
|
||||
|
||||
// MODULE: m3-js()()(m1-common)
|
||||
|
||||
Vendored
+4
-4
@@ -18,10 +18,10 @@ expect fun f8(vararg x: Any)
|
||||
// FILE: jvm.kt
|
||||
|
||||
actual inline fun f1(noinline s: () -> String) {}
|
||||
actual inline fun f2(noinline s: () -> String) {}
|
||||
<!ACTUAL_WITHOUT_EXPECT!>actual inline fun f2(noinline s: () -> String) {}<!>
|
||||
actual inline fun f3(s: () -> String) {}
|
||||
actual inline fun f4(crossinline s: () -> String) {}
|
||||
actual inline fun f5(crossinline s: () -> String) {}
|
||||
<!ACTUAL_WITHOUT_EXPECT!>actual inline fun f5(crossinline s: () -> String) {}<!>
|
||||
actual inline fun f6(s: () -> String) {}
|
||||
actual fun f7(vararg x: Any) {}
|
||||
actual fun f8(x: Any) {}
|
||||
<!ACTUAL_WITHOUT_EXPECT!>actual fun f7(vararg x: Any) {}<!>
|
||||
<!ACTUAL_WITHOUT_EXPECT!>actual fun f8(x: Any) {}<!>
|
||||
|
||||
@@ -5,6 +5,7 @@ plugins {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(project(":compiler:resolution.common"))
|
||||
implementation(project(":compiler:fir:tree"))
|
||||
implementation(project(":compiler:fir:tree:tree-generator"))
|
||||
implementation(project(":compiler:fir:checkers:checkers-component-generator"))
|
||||
|
||||
+4
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
|
||||
import org.jetbrains.kotlin.descriptors.EffectiveVisibility
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.diagnostics.WhenMissingCase
|
||||
import org.jetbrains.kotlin.fir.FirModuleData
|
||||
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.DiagnosticData
|
||||
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.DiagnosticList
|
||||
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.DiagnosticParameter
|
||||
@@ -30,6 +31,7 @@ import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.resolve.ForbiddenNamedArgumentsTarget
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KType
|
||||
@@ -296,6 +298,8 @@ private object FirToKtConversionCreator {
|
||||
LanguageVersionSettings::class,
|
||||
Variance::class,
|
||||
FqName::class,
|
||||
FirModuleData::class,
|
||||
ExpectActualCompatibility.Incompatible::class,
|
||||
)
|
||||
|
||||
private val KType.kClass: KClass<*>
|
||||
|
||||
+160
-6
@@ -26,10 +26,14 @@ import org.jetbrains.kotlin.psi.KtBinaryExpressionWithTypeRHS
|
||||
import org.jetbrains.kotlin.psi.KtCallExpression
|
||||
import org.jetbrains.kotlin.psi.KtClass
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
import org.jetbrains.kotlin.psi.KtConstructor
|
||||
import org.jetbrains.kotlin.psi.KtConstructorDelegationCall
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtDeclarationWithBody
|
||||
import org.jetbrains.kotlin.psi.KtDelegatedSuperTypeEntry
|
||||
import org.jetbrains.kotlin.psi.KtDestructuringDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtEnumEntry
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.psi.KtFunction
|
||||
import org.jetbrains.kotlin.psi.KtIfExpression
|
||||
@@ -2129,12 +2133,6 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.EXPECTED_PRIVATE_DECLARATION) { firDiagnostic ->
|
||||
ExpectedPrivateDeclarationImpl(
|
||||
firDiagnostic as FirPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.VAL_WITH_SETTER) { firDiagnostic ->
|
||||
ValWithSetterImpl(
|
||||
firDiagnostic as FirPsiDiagnostic,
|
||||
@@ -2232,6 +2230,30 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.EXPECTED_CLASS_CONSTRUCTOR_DELEGATION_CALL) { firDiagnostic ->
|
||||
ExpectedClassConstructorDelegationCallImpl(
|
||||
firDiagnostic as FirPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.EXPECTED_CLASS_CONSTRUCTOR_PROPERTY_PARAMETER) { firDiagnostic ->
|
||||
ExpectedClassConstructorPropertyParameterImpl(
|
||||
firDiagnostic as FirPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.EXPECTED_ENUM_CONSTRUCTOR) { firDiagnostic ->
|
||||
ExpectedEnumConstructorImpl(
|
||||
firDiagnostic as FirPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.EXPECTED_ENUM_ENTRY_WITH_BODY) { firDiagnostic ->
|
||||
ExpectedEnumEntryWithBodyImpl(
|
||||
firDiagnostic as FirPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.EXPECTED_PROPERTY_INITIALIZER) { firDiagnostic ->
|
||||
ExpectedPropertyInitializerImpl(
|
||||
firDiagnostic as FirPsiDiagnostic,
|
||||
@@ -2250,6 +2272,138 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.SUPERTYPE_INITIALIZED_IN_EXPECTED_CLASS) { firDiagnostic ->
|
||||
SupertypeInitializedInExpectedClassImpl(
|
||||
firDiagnostic as FirPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.EXPECTED_PRIVATE_DECLARATION) { firDiagnostic ->
|
||||
ExpectedPrivateDeclarationImpl(
|
||||
firDiagnostic as FirPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.IMPLEMENTATION_BY_DELEGATION_IN_EXPECT_CLASS) { firDiagnostic ->
|
||||
ImplementationByDelegationInExpectClassImpl(
|
||||
firDiagnostic as FirPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.ACTUAL_TYPE_ALIAS_NOT_TO_CLASS) { firDiagnostic ->
|
||||
ActualTypeAliasNotToClassImpl(
|
||||
firDiagnostic as FirPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.ACTUAL_TYPE_ALIAS_TO_CLASS_WITH_DECLARATION_SITE_VARIANCE) { firDiagnostic ->
|
||||
ActualTypeAliasToClassWithDeclarationSiteVarianceImpl(
|
||||
firDiagnostic as FirPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.ACTUAL_TYPE_ALIAS_WITH_USE_SITE_VARIANCE) { firDiagnostic ->
|
||||
ActualTypeAliasWithUseSiteVarianceImpl(
|
||||
firDiagnostic as FirPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.ACTUAL_TYPE_ALIAS_WITH_COMPLEX_SUBSTITUTION) { firDiagnostic ->
|
||||
ActualTypeAliasWithComplexSubstitutionImpl(
|
||||
firDiagnostic as FirPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS) { firDiagnostic ->
|
||||
ActualFunctionWithDefaultArgumentsImpl(
|
||||
firDiagnostic as FirPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.ACTUAL_ANNOTATION_CONFLICTING_DEFAULT_ARGUMENT_VALUE) { firDiagnostic ->
|
||||
ActualAnnotationConflictingDefaultArgumentValueImpl(
|
||||
firSymbolBuilder.variableLikeBuilder.buildVariableLikeSymbol(firDiagnostic.a.fir),
|
||||
firDiagnostic as FirPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.EXPECTED_FUNCTION_SOURCE_WITH_DEFAULT_ARGUMENTS_NOT_FOUND) { firDiagnostic ->
|
||||
ExpectedFunctionSourceWithDefaultArgumentsNotFoundImpl(
|
||||
firDiagnostic as FirPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.NO_ACTUAL_FOR_EXPECT) { firDiagnostic ->
|
||||
NoActualForExpectImpl(
|
||||
firSymbolBuilder.buildSymbol(firDiagnostic.a.fir),
|
||||
firDiagnostic.b,
|
||||
firDiagnostic.c.mapKeys { (incompatible, _) ->
|
||||
incompatible
|
||||
}.mapValues { (_, collection) ->
|
||||
collection.map { firBasedSymbol ->
|
||||
firSymbolBuilder.buildSymbol(firBasedSymbol.fir)
|
||||
}
|
||||
},
|
||||
firDiagnostic as FirPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.ACTUAL_WITHOUT_EXPECT) { firDiagnostic ->
|
||||
ActualWithoutExpectImpl(
|
||||
firSymbolBuilder.buildSymbol(firDiagnostic.a.fir),
|
||||
firDiagnostic.b.mapKeys { (incompatible, _) ->
|
||||
incompatible
|
||||
}.mapValues { (_, collection) ->
|
||||
collection.map { firBasedSymbol ->
|
||||
firSymbolBuilder.buildSymbol(firBasedSymbol.fir)
|
||||
}
|
||||
},
|
||||
firDiagnostic as FirPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.AMBIGUOUS_ACTUALS) { firDiagnostic ->
|
||||
AmbiguousActualsImpl(
|
||||
firSymbolBuilder.buildSymbol(firDiagnostic.a.fir),
|
||||
firDiagnostic.b.map { firBasedSymbol ->
|
||||
firSymbolBuilder.buildSymbol(firBasedSymbol.fir)
|
||||
},
|
||||
firDiagnostic as FirPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.AMBIGUOUS_EXPECTS) { firDiagnostic ->
|
||||
AmbiguousExpectsImpl(
|
||||
firSymbolBuilder.buildSymbol(firDiagnostic.a.fir),
|
||||
firDiagnostic.b.map { firModuleData ->
|
||||
firModuleData
|
||||
},
|
||||
firDiagnostic as FirPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS) { firDiagnostic ->
|
||||
NoActualClassMemberForExpectedClassImpl(
|
||||
firSymbolBuilder.buildSymbol(firDiagnostic.a.fir),
|
||||
firDiagnostic.b.map { pair ->
|
||||
firSymbolBuilder.buildSymbol(pair.first.fir) to pair.second.mapKeys { (incompatible, _) ->
|
||||
incompatible
|
||||
}.mapValues { (_, collection) ->
|
||||
collection.map { firBasedSymbol ->
|
||||
firSymbolBuilder.buildSymbol(firBasedSymbol.fir)
|
||||
}
|
||||
}
|
||||
},
|
||||
firDiagnostic as FirPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.ACTUAL_MISSING) { firDiagnostic ->
|
||||
ActualMissingImpl(
|
||||
firDiagnostic as FirPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION) { firDiagnostic ->
|
||||
InitializerRequiredForDestructuringDeclarationImpl(
|
||||
firDiagnostic as FirPsiDiagnostic,
|
||||
|
||||
+99
-4
@@ -13,6 +13,8 @@ import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
|
||||
import org.jetbrains.kotlin.descriptors.EffectiveVisibility
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.diagnostics.WhenMissingCase
|
||||
import org.jetbrains.kotlin.fir.FirModuleData
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.idea.frontend.api.diagnostics.KtDiagnosticWithPsi
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCallableSymbol
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtClassLikeSymbol
|
||||
@@ -33,10 +35,14 @@ import org.jetbrains.kotlin.psi.KtBinaryExpressionWithTypeRHS
|
||||
import org.jetbrains.kotlin.psi.KtCallExpression
|
||||
import org.jetbrains.kotlin.psi.KtClass
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
import org.jetbrains.kotlin.psi.KtConstructor
|
||||
import org.jetbrains.kotlin.psi.KtConstructorDelegationCall
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtDeclarationWithBody
|
||||
import org.jetbrains.kotlin.psi.KtDelegatedSuperTypeEntry
|
||||
import org.jetbrains.kotlin.psi.KtDestructuringDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtEnumEntry
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.psi.KtFunction
|
||||
import org.jetbrains.kotlin.psi.KtIfExpression
|
||||
@@ -59,6 +65,7 @@ import org.jetbrains.kotlin.psi.KtWhenCondition
|
||||
import org.jetbrains.kotlin.psi.KtWhenEntry
|
||||
import org.jetbrains.kotlin.psi.KtWhenExpression
|
||||
import org.jetbrains.kotlin.resolve.ForbiddenNamedArgumentsTarget
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility.Incompatible
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
|
||||
/*
|
||||
@@ -1504,10 +1511,6 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
||||
override val diagnosticClass get() = PrivateSetterForOpenProperty::class
|
||||
}
|
||||
|
||||
abstract class ExpectedPrivateDeclaration : KtFirDiagnostic<KtModifierListOwner>() {
|
||||
override val diagnosticClass get() = ExpectedPrivateDeclaration::class
|
||||
}
|
||||
|
||||
abstract class ValWithSetter : KtFirDiagnostic<KtPropertyAccessor>() {
|
||||
override val diagnosticClass get() = ValWithSetter::class
|
||||
}
|
||||
@@ -1575,6 +1578,22 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
||||
override val diagnosticClass get() = ExpectedDeclarationWithBody::class
|
||||
}
|
||||
|
||||
abstract class ExpectedClassConstructorDelegationCall : KtFirDiagnostic<KtConstructorDelegationCall>() {
|
||||
override val diagnosticClass get() = ExpectedClassConstructorDelegationCall::class
|
||||
}
|
||||
|
||||
abstract class ExpectedClassConstructorPropertyParameter : KtFirDiagnostic<KtParameter>() {
|
||||
override val diagnosticClass get() = ExpectedClassConstructorPropertyParameter::class
|
||||
}
|
||||
|
||||
abstract class ExpectedEnumConstructor : KtFirDiagnostic<KtConstructor<*>>() {
|
||||
override val diagnosticClass get() = ExpectedEnumConstructor::class
|
||||
}
|
||||
|
||||
abstract class ExpectedEnumEntryWithBody : KtFirDiagnostic<KtEnumEntry>() {
|
||||
override val diagnosticClass get() = ExpectedEnumEntryWithBody::class
|
||||
}
|
||||
|
||||
abstract class ExpectedPropertyInitializer : KtFirDiagnostic<KtExpression>() {
|
||||
override val diagnosticClass get() = ExpectedPropertyInitializer::class
|
||||
}
|
||||
@@ -1587,6 +1606,82 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
||||
override val diagnosticClass get() = ExpectedLateinitProperty::class
|
||||
}
|
||||
|
||||
abstract class SupertypeInitializedInExpectedClass : KtFirDiagnostic<PsiElement>() {
|
||||
override val diagnosticClass get() = SupertypeInitializedInExpectedClass::class
|
||||
}
|
||||
|
||||
abstract class ExpectedPrivateDeclaration : KtFirDiagnostic<KtModifierListOwner>() {
|
||||
override val diagnosticClass get() = ExpectedPrivateDeclaration::class
|
||||
}
|
||||
|
||||
abstract class ImplementationByDelegationInExpectClass : KtFirDiagnostic<KtDelegatedSuperTypeEntry>() {
|
||||
override val diagnosticClass get() = ImplementationByDelegationInExpectClass::class
|
||||
}
|
||||
|
||||
abstract class ActualTypeAliasNotToClass : KtFirDiagnostic<KtTypeAlias>() {
|
||||
override val diagnosticClass get() = ActualTypeAliasNotToClass::class
|
||||
}
|
||||
|
||||
abstract class ActualTypeAliasToClassWithDeclarationSiteVariance : KtFirDiagnostic<KtTypeAlias>() {
|
||||
override val diagnosticClass get() = ActualTypeAliasToClassWithDeclarationSiteVariance::class
|
||||
}
|
||||
|
||||
abstract class ActualTypeAliasWithUseSiteVariance : KtFirDiagnostic<KtTypeAlias>() {
|
||||
override val diagnosticClass get() = ActualTypeAliasWithUseSiteVariance::class
|
||||
}
|
||||
|
||||
abstract class ActualTypeAliasWithComplexSubstitution : KtFirDiagnostic<KtTypeAlias>() {
|
||||
override val diagnosticClass get() = ActualTypeAliasWithComplexSubstitution::class
|
||||
}
|
||||
|
||||
abstract class ActualFunctionWithDefaultArguments : KtFirDiagnostic<PsiElement>() {
|
||||
override val diagnosticClass get() = ActualFunctionWithDefaultArguments::class
|
||||
}
|
||||
|
||||
abstract class ActualAnnotationConflictingDefaultArgumentValue : KtFirDiagnostic<PsiElement>() {
|
||||
override val diagnosticClass get() = ActualAnnotationConflictingDefaultArgumentValue::class
|
||||
abstract val parameter: KtVariableLikeSymbol
|
||||
}
|
||||
|
||||
abstract class ExpectedFunctionSourceWithDefaultArgumentsNotFound : KtFirDiagnostic<PsiElement>() {
|
||||
override val diagnosticClass get() = ExpectedFunctionSourceWithDefaultArgumentsNotFound::class
|
||||
}
|
||||
|
||||
abstract class NoActualForExpect : KtFirDiagnostic<KtNamedDeclaration>() {
|
||||
override val diagnosticClass get() = NoActualForExpect::class
|
||||
abstract val declaration: KtSymbol
|
||||
abstract val module: FirModuleData
|
||||
abstract val compatibility: Map<Incompatible<FirBasedSymbol<*>>, List<KtSymbol>>
|
||||
}
|
||||
|
||||
abstract class ActualWithoutExpect : KtFirDiagnostic<KtNamedDeclaration>() {
|
||||
override val diagnosticClass get() = ActualWithoutExpect::class
|
||||
abstract val declaration: KtSymbol
|
||||
abstract val compatibility: Map<Incompatible<FirBasedSymbol<*>>, List<KtSymbol>>
|
||||
}
|
||||
|
||||
abstract class AmbiguousActuals : KtFirDiagnostic<KtNamedDeclaration>() {
|
||||
override val diagnosticClass get() = AmbiguousActuals::class
|
||||
abstract val declaration: KtSymbol
|
||||
abstract val candidates: List<KtSymbol>
|
||||
}
|
||||
|
||||
abstract class AmbiguousExpects : KtFirDiagnostic<KtNamedDeclaration>() {
|
||||
override val diagnosticClass get() = AmbiguousExpects::class
|
||||
abstract val declaration: KtSymbol
|
||||
abstract val modules: List<FirModuleData>
|
||||
}
|
||||
|
||||
abstract class NoActualClassMemberForExpectedClass : KtFirDiagnostic<KtNamedDeclaration>() {
|
||||
override val diagnosticClass get() = NoActualClassMemberForExpectedClass::class
|
||||
abstract val declaration: KtSymbol
|
||||
abstract val members: List<Pair<KtSymbol, Map<Incompatible<FirBasedSymbol<*>>, List<KtSymbol>>>>
|
||||
}
|
||||
|
||||
abstract class ActualMissing : KtFirDiagnostic<KtNamedDeclaration>() {
|
||||
override val diagnosticClass get() = ActualMissing::class
|
||||
}
|
||||
|
||||
abstract class InitializerRequiredForDestructuringDeclaration : KtFirDiagnostic<KtDestructuringDeclaration>() {
|
||||
override val diagnosticClass get() = InitializerRequiredForDestructuringDeclaration::class
|
||||
}
|
||||
|
||||
+159
-7
@@ -13,7 +13,9 @@ import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
|
||||
import org.jetbrains.kotlin.descriptors.EffectiveVisibility
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.diagnostics.WhenMissingCase
|
||||
import org.jetbrains.kotlin.fir.FirModuleData
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirPsiDiagnostic
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCallableSymbol
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtClassLikeSymbol
|
||||
@@ -35,10 +37,14 @@ import org.jetbrains.kotlin.psi.KtBinaryExpressionWithTypeRHS
|
||||
import org.jetbrains.kotlin.psi.KtCallExpression
|
||||
import org.jetbrains.kotlin.psi.KtClass
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
import org.jetbrains.kotlin.psi.KtConstructor
|
||||
import org.jetbrains.kotlin.psi.KtConstructorDelegationCall
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtDeclarationWithBody
|
||||
import org.jetbrains.kotlin.psi.KtDelegatedSuperTypeEntry
|
||||
import org.jetbrains.kotlin.psi.KtDestructuringDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtEnumEntry
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.psi.KtFunction
|
||||
import org.jetbrains.kotlin.psi.KtIfExpression
|
||||
@@ -61,6 +67,7 @@ import org.jetbrains.kotlin.psi.KtWhenCondition
|
||||
import org.jetbrains.kotlin.psi.KtWhenEntry
|
||||
import org.jetbrains.kotlin.psi.KtWhenExpression
|
||||
import org.jetbrains.kotlin.resolve.ForbiddenNamedArgumentsTarget
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility.Incompatible
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
|
||||
/*
|
||||
@@ -2423,13 +2430,6 @@ internal class PrivateSetterForOpenPropertyImpl(
|
||||
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class ExpectedPrivateDeclarationImpl(
|
||||
firDiagnostic: FirPsiDiagnostic,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.ExpectedPrivateDeclaration(), KtAbstractFirDiagnostic<KtModifierListOwner> {
|
||||
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class ValWithSetterImpl(
|
||||
firDiagnostic: FirPsiDiagnostic,
|
||||
override val token: ValidityToken,
|
||||
@@ -2542,6 +2542,34 @@ internal class ExpectedDeclarationWithBodyImpl(
|
||||
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class ExpectedClassConstructorDelegationCallImpl(
|
||||
firDiagnostic: FirPsiDiagnostic,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.ExpectedClassConstructorDelegationCall(), KtAbstractFirDiagnostic<KtConstructorDelegationCall> {
|
||||
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class ExpectedClassConstructorPropertyParameterImpl(
|
||||
firDiagnostic: FirPsiDiagnostic,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.ExpectedClassConstructorPropertyParameter(), KtAbstractFirDiagnostic<KtParameter> {
|
||||
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class ExpectedEnumConstructorImpl(
|
||||
firDiagnostic: FirPsiDiagnostic,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.ExpectedEnumConstructor(), KtAbstractFirDiagnostic<KtConstructor<*>> {
|
||||
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class ExpectedEnumEntryWithBodyImpl(
|
||||
firDiagnostic: FirPsiDiagnostic,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.ExpectedEnumEntryWithBody(), KtAbstractFirDiagnostic<KtEnumEntry> {
|
||||
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class ExpectedPropertyInitializerImpl(
|
||||
firDiagnostic: FirPsiDiagnostic,
|
||||
override val token: ValidityToken,
|
||||
@@ -2563,6 +2591,130 @@ internal class ExpectedLateinitPropertyImpl(
|
||||
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class SupertypeInitializedInExpectedClassImpl(
|
||||
firDiagnostic: FirPsiDiagnostic,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.SupertypeInitializedInExpectedClass(), KtAbstractFirDiagnostic<PsiElement> {
|
||||
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class ExpectedPrivateDeclarationImpl(
|
||||
firDiagnostic: FirPsiDiagnostic,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.ExpectedPrivateDeclaration(), KtAbstractFirDiagnostic<KtModifierListOwner> {
|
||||
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class ImplementationByDelegationInExpectClassImpl(
|
||||
firDiagnostic: FirPsiDiagnostic,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.ImplementationByDelegationInExpectClass(), KtAbstractFirDiagnostic<KtDelegatedSuperTypeEntry> {
|
||||
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class ActualTypeAliasNotToClassImpl(
|
||||
firDiagnostic: FirPsiDiagnostic,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.ActualTypeAliasNotToClass(), KtAbstractFirDiagnostic<KtTypeAlias> {
|
||||
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class ActualTypeAliasToClassWithDeclarationSiteVarianceImpl(
|
||||
firDiagnostic: FirPsiDiagnostic,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.ActualTypeAliasToClassWithDeclarationSiteVariance(), KtAbstractFirDiagnostic<KtTypeAlias> {
|
||||
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class ActualTypeAliasWithUseSiteVarianceImpl(
|
||||
firDiagnostic: FirPsiDiagnostic,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.ActualTypeAliasWithUseSiteVariance(), KtAbstractFirDiagnostic<KtTypeAlias> {
|
||||
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class ActualTypeAliasWithComplexSubstitutionImpl(
|
||||
firDiagnostic: FirPsiDiagnostic,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.ActualTypeAliasWithComplexSubstitution(), KtAbstractFirDiagnostic<KtTypeAlias> {
|
||||
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class ActualFunctionWithDefaultArgumentsImpl(
|
||||
firDiagnostic: FirPsiDiagnostic,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.ActualFunctionWithDefaultArguments(), KtAbstractFirDiagnostic<PsiElement> {
|
||||
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class ActualAnnotationConflictingDefaultArgumentValueImpl(
|
||||
override val parameter: KtVariableLikeSymbol,
|
||||
firDiagnostic: FirPsiDiagnostic,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.ActualAnnotationConflictingDefaultArgumentValue(), KtAbstractFirDiagnostic<PsiElement> {
|
||||
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class ExpectedFunctionSourceWithDefaultArgumentsNotFoundImpl(
|
||||
firDiagnostic: FirPsiDiagnostic,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.ExpectedFunctionSourceWithDefaultArgumentsNotFound(), KtAbstractFirDiagnostic<PsiElement> {
|
||||
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class NoActualForExpectImpl(
|
||||
override val declaration: KtSymbol,
|
||||
override val module: FirModuleData,
|
||||
override val compatibility: Map<Incompatible<FirBasedSymbol<*>>, List<KtSymbol>>,
|
||||
firDiagnostic: FirPsiDiagnostic,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.NoActualForExpect(), KtAbstractFirDiagnostic<KtNamedDeclaration> {
|
||||
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class ActualWithoutExpectImpl(
|
||||
override val declaration: KtSymbol,
|
||||
override val compatibility: Map<Incompatible<FirBasedSymbol<*>>, List<KtSymbol>>,
|
||||
firDiagnostic: FirPsiDiagnostic,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.ActualWithoutExpect(), KtAbstractFirDiagnostic<KtNamedDeclaration> {
|
||||
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class AmbiguousActualsImpl(
|
||||
override val declaration: KtSymbol,
|
||||
override val candidates: List<KtSymbol>,
|
||||
firDiagnostic: FirPsiDiagnostic,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.AmbiguousActuals(), KtAbstractFirDiagnostic<KtNamedDeclaration> {
|
||||
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class AmbiguousExpectsImpl(
|
||||
override val declaration: KtSymbol,
|
||||
override val modules: List<FirModuleData>,
|
||||
firDiagnostic: FirPsiDiagnostic,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.AmbiguousExpects(), KtAbstractFirDiagnostic<KtNamedDeclaration> {
|
||||
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class NoActualClassMemberForExpectedClassImpl(
|
||||
override val declaration: KtSymbol,
|
||||
override val members: List<Pair<KtSymbol, Map<Incompatible<FirBasedSymbol<*>>, List<KtSymbol>>>>,
|
||||
firDiagnostic: FirPsiDiagnostic,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.NoActualClassMemberForExpectedClass(), KtAbstractFirDiagnostic<KtNamedDeclaration> {
|
||||
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class ActualMissingImpl(
|
||||
firDiagnostic: FirPsiDiagnostic,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.ActualMissing(), KtAbstractFirDiagnostic<KtNamedDeclaration> {
|
||||
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class InitializerRequiredForDestructuringDeclarationImpl(
|
||||
firDiagnostic: FirPsiDiagnostic,
|
||||
override val token: ValidityToken,
|
||||
|
||||
Reference in New Issue
Block a user