[FIR JS] Support DYNAMIC_RECEIVER_NOT_ALLOWED
This commit is contained in:
committed by
Space Team
parent
0f876f665a
commit
227969d787
+6
@@ -2022,6 +2022,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.DYNAMIC_RECEIVER_NOT_ALLOWED) { firDiagnostic ->
|
||||
DynamicReceiverNotAllowedImpl(
|
||||
firDiagnostic as KtPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.INCOMPATIBLE_TYPES) { firDiagnostic ->
|
||||
IncompatibleTypesImpl(
|
||||
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a),
|
||||
|
||||
+4
@@ -1435,6 +1435,10 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
||||
override val diagnosticClass get() = DynamicUpperBound::class
|
||||
}
|
||||
|
||||
abstract class DynamicReceiverNotAllowed : KtFirDiagnostic<KtElement>() {
|
||||
override val diagnosticClass get() = DynamicReceiverNotAllowed::class
|
||||
}
|
||||
|
||||
abstract class IncompatibleTypes : KtFirDiagnostic<KtElement>() {
|
||||
override val diagnosticClass get() = IncompatibleTypes::class
|
||||
abstract val typeA: KtType
|
||||
|
||||
+5
@@ -1727,6 +1727,11 @@ internal class DynamicUpperBoundImpl(
|
||||
override val token: KtLifetimeToken,
|
||||
) : KtFirDiagnostic.DynamicUpperBound(), KtAbstractFirDiagnostic<KtTypeReference>
|
||||
|
||||
internal class DynamicReceiverNotAllowedImpl(
|
||||
override val firDiagnostic: KtPsiDiagnostic,
|
||||
override val token: KtLifetimeToken,
|
||||
) : KtFirDiagnostic.DynamicReceiverNotAllowed(), KtAbstractFirDiagnostic<KtElement>
|
||||
|
||||
internal class IncompatibleTypesImpl(
|
||||
override val typeA: KtType,
|
||||
override val typeB: KtType,
|
||||
|
||||
+2
@@ -674,6 +674,8 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
||||
|
||||
val DYNAMIC_UPPER_BOUND by error<KtTypeReference>()
|
||||
|
||||
val DYNAMIC_RECEIVER_NOT_ALLOWED by error<KtElement>()
|
||||
|
||||
val INCOMPATIBLE_TYPES by error<KtElement> {
|
||||
parameter<ConeKotlinType>("typeA")
|
||||
parameter<ConeKotlinType>("typeB")
|
||||
|
||||
@@ -417,6 +417,7 @@ object FirErrors {
|
||||
val DEPRECATED_TYPE_PARAMETER_SYNTAX by error0<KtDeclaration>(SourceElementPositioningStrategies.TYPE_PARAMETERS_LIST)
|
||||
val MISPLACED_TYPE_PARAMETER_CONSTRAINTS by warning0<KtTypeParameter>()
|
||||
val DYNAMIC_UPPER_BOUND by error0<KtTypeReference>()
|
||||
val DYNAMIC_RECEIVER_NOT_ALLOWED by error0<KtElement>()
|
||||
val INCOMPATIBLE_TYPES by error2<KtElement, ConeKotlinType, ConeKotlinType>()
|
||||
val INCOMPATIBLE_TYPES_WARNING by warning2<KtElement, ConeKotlinType, ConeKotlinType>()
|
||||
val TYPE_VARIANCE_CONFLICT_ERROR by error4<PsiElement, FirTypeParameterSymbol, Variance, Variance, ConeKotlinType>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT)
|
||||
|
||||
+1
@@ -38,6 +38,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
|
||||
get() = setOf(
|
||||
FirKClassWithIncorrectTypeArgumentChecker,
|
||||
FirImplicitNothingReturnTypeChecker,
|
||||
FirDynamicReceiverChecker,
|
||||
)
|
||||
|
||||
override val functionCheckers: Set<FirFunctionChecker>
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.hasAnnotation
|
||||
import org.jetbrains.kotlin.fir.types.ConeDynamicType
|
||||
import org.jetbrains.kotlin.fir.types.coneType
|
||||
import org.jetbrains.kotlin.name.StandardClassIds.Annotations.DynamicExtension
|
||||
|
||||
object FirDynamicReceiverChecker : FirCallableDeclarationChecker() {
|
||||
override fun check(declaration: FirCallableDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
if (
|
||||
declaration.receiverParameter?.typeRef?.coneType is ConeDynamicType &&
|
||||
!declaration.hasAnnotation(DynamicExtension, context.session) &&
|
||||
declaration !is FirAnonymousFunction
|
||||
) {
|
||||
reporter.reportOn(declaration.receiverParameter?.source, FirErrors.DYNAMIC_RECEIVER_NOT_ALLOWED, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
@@ -168,6 +168,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DESERIALIZATION_E
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DIVISION_BY_ZERO
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DSL_SCOPE_VIOLATION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DUPLICATE_LABEL_IN_WHEN
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DYNAMIC_RECEIVER_NOT_ALLOWED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DYNAMIC_UPPER_BOUND
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ELSE_MISPLACED_IN_WHEN
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EMPTY_CHARACTER_LITERAL
|
||||
@@ -1251,6 +1252,8 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
|
||||
|
||||
map.put(DYNAMIC_UPPER_BOUND, "Dynamic type can not be used as an upper bound")
|
||||
|
||||
map.put(DYNAMIC_RECEIVER_NOT_ALLOWED, "Dynamic receiver is prohibited")
|
||||
|
||||
// Reflection
|
||||
map.put(
|
||||
EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED,
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ public class J {
|
||||
import p.*
|
||||
|
||||
class K: J.C() {
|
||||
fun <!UNSUPPORTED!>dynamic<!>.test() {
|
||||
fun <!DYNAMIC_RECEIVER_NOT_ALLOWED, UNSUPPORTED!>dynamic<!>.test() {
|
||||
sam(null)
|
||||
sam(
|
||||
name = null,
|
||||
|
||||
-9
@@ -1,9 +0,0 @@
|
||||
object X1
|
||||
object X2
|
||||
|
||||
class Inv<T>
|
||||
|
||||
fun dynamic.foo() = X1
|
||||
fun <T> Inv<T>.foo() = X2
|
||||
|
||||
fun test(): X2 = Inv<Any>().foo()
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
object X1
|
||||
object X2
|
||||
|
||||
|
||||
+1
-1
@@ -41,7 +41,7 @@ fun testReassignmentWithStaticCalls(d: dynamic) {
|
||||
val Any.onAnyVal: Int get() = 1
|
||||
val Any?.onNullableAnyVal: Int get() = 1
|
||||
val String.onStringVal: Int get() = 1
|
||||
val dynamic.onDynamicVal: Int get() = 1
|
||||
val <!DYNAMIC_RECEIVER_NOT_ALLOWED!>dynamic<!>.onDynamicVal: Int get() = 1
|
||||
|
||||
class C {
|
||||
fun test(d: dynamic) {
|
||||
|
||||
+1
-1
@@ -47,7 +47,7 @@ var String.onStringVar: Int
|
||||
get() = 1
|
||||
set(v) {}
|
||||
|
||||
var dynamic.onDynamicVar: Int
|
||||
var <!DYNAMIC_RECEIVER_NOT_ALLOWED!>dynamic<!>.onDynamicVar: Int
|
||||
get() = 1
|
||||
set(v) {}
|
||||
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ fun test(d: dynamic) {
|
||||
fun Any.onAny() {}
|
||||
fun Any?.onNullableAny() {}
|
||||
fun String.onString() {}
|
||||
fun dynamic.onDynamic() {}
|
||||
fun <!DYNAMIC_RECEIVER_NOT_ALLOWED!>dynamic<!>.onDynamic() {}
|
||||
|
||||
class C {
|
||||
fun test(d: dynamic) {
|
||||
|
||||
+7
-7
@@ -11,7 +11,7 @@ fun test(d: dynamic) {
|
||||
d.<!DEBUG_INFO_DYNAMIC!>varOnDynamic<!> = 1
|
||||
}
|
||||
|
||||
fun dynamic.extTest() {
|
||||
fun <!DYNAMIC_RECEIVER_NOT_ALLOWED!>dynamic<!>.extTest() {
|
||||
<!DEBUG_INFO_DYNAMIC!>onDynamic<!>()
|
||||
<!DEBUG_INFO_DYNAMIC!>onNullableDynamic<!>()
|
||||
|
||||
@@ -32,12 +32,12 @@ fun dynamic.extTest() {
|
||||
|
||||
}
|
||||
|
||||
fun dynamic.onDynamic() {}
|
||||
fun dynamic?.onNullableDynamic() {}
|
||||
fun <!DYNAMIC_RECEIVER_NOT_ALLOWED!>dynamic<!>.onDynamic() {}
|
||||
fun <!DYNAMIC_RECEIVER_NOT_ALLOWED!>dynamic?<!>.onNullableDynamic() {}
|
||||
|
||||
val dynamic.valOnDynamic: Int get() = 1
|
||||
val <!DYNAMIC_RECEIVER_NOT_ALLOWED!>dynamic<!>.valOnDynamic: Int get() = 1
|
||||
|
||||
var dynamic.varOnDynamic: Int
|
||||
var <!DYNAMIC_RECEIVER_NOT_ALLOWED!>dynamic<!>.varOnDynamic: Int
|
||||
get() = 1
|
||||
set(v) {}
|
||||
|
||||
@@ -51,8 +51,8 @@ class ForMemberExtensions {
|
||||
d.<!DEBUG_INFO_DYNAMIC!>memberExtensionVal<!> = 1
|
||||
}
|
||||
|
||||
val dynamic.memberExtensionVal: Int get() = 1
|
||||
var dynamic.memberExtensionVar: Int
|
||||
val <!DYNAMIC_RECEIVER_NOT_ALLOWED!>dynamic<!>.memberExtensionVal: Int get() = 1
|
||||
var <!DYNAMIC_RECEIVER_NOT_ALLOWED!>dynamic<!>.memberExtensionVar: Int
|
||||
get() = 1
|
||||
set(v) {}
|
||||
}
|
||||
|
||||
Vendored
-18
@@ -1,18 +0,0 @@
|
||||
fun dynamic.test() {
|
||||
val v1 = foo()
|
||||
v1.isDynamic() // to check that anything is resolvable
|
||||
|
||||
val v2 = foo(1)
|
||||
v2.isDynamic() // to check that anything is resolvable
|
||||
|
||||
val v3 = foo(1, "")
|
||||
v3.isDynamic() // to check that anything is resolvable
|
||||
|
||||
val v4 = foo<String>()
|
||||
v4.isDynamic() // to check that anything is resolvable
|
||||
|
||||
val v5 = foo
|
||||
v5.isDynamic() // to check that anything is resolvable
|
||||
|
||||
foo = 1
|
||||
}
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
fun <!DYNAMIC_RECEIVER_NOT_ALLOWED!>dynamic<!>.test() {
|
||||
val v1 = foo()
|
||||
v1.isDynamic() // to check that anything is resolvable
|
||||
|
||||
-11
@@ -1,11 +0,0 @@
|
||||
// !MARK_DYNAMIC_CALLS
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
|
||||
fun dynamic.foo(s: String, a: Any) {}
|
||||
fun dynamic.foo(s: Any, a: String) {}
|
||||
|
||||
fun test(d: dynamic) {
|
||||
d.<!DEBUG_INFO_DYNAMIC!>foo<!>(1, "")
|
||||
d.<!DEBUG_INFO_DYNAMIC!>foo<!>("", "")
|
||||
d.<!DEBUG_INFO_DYNAMIC!>foo<!>(1, 1)
|
||||
}
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// !MARK_DYNAMIC_CALLS
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
|
||||
|
||||
Vendored
+2
-2
@@ -1,7 +1,7 @@
|
||||
// !MARK_DYNAMIC_CALLS
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
|
||||
fun dynamic.test() {
|
||||
fun <!DYNAMIC_RECEIVER_NOT_ALLOWED!>dynamic<!>.test() {
|
||||
<!DEBUG_INFO_DYNAMIC!>foo<!>()
|
||||
<!DEBUG_INFO_DYNAMIC!>ext<!>()
|
||||
|
||||
@@ -57,7 +57,7 @@ class C {
|
||||
|
||||
val withInvoke = WithInvoke()
|
||||
|
||||
fun dynamic.test() {
|
||||
fun <!DYNAMIC_RECEIVER_NOT_ALLOWED!>dynamic<!>.test() {
|
||||
s()
|
||||
this()
|
||||
|
||||
|
||||
@@ -149,6 +149,7 @@ object StandardClassIds {
|
||||
val DeprecatedSinceKotlin = "DeprecatedSinceKotlin".baseId()
|
||||
|
||||
val HidesMembers = "HidesMembers".internalId()
|
||||
val DynamicExtension = "DynamicExtension".internalId()
|
||||
|
||||
val Retention = "Retention".annotationId()
|
||||
val Target = "Target".annotationId()
|
||||
|
||||
Reference in New Issue
Block a user