[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,
|
token,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
add(FirErrors.DYNAMIC_RECEIVER_NOT_ALLOWED) { firDiagnostic ->
|
||||||
|
DynamicReceiverNotAllowedImpl(
|
||||||
|
firDiagnostic as KtPsiDiagnostic,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
add(FirErrors.INCOMPATIBLE_TYPES) { firDiagnostic ->
|
add(FirErrors.INCOMPATIBLE_TYPES) { firDiagnostic ->
|
||||||
IncompatibleTypesImpl(
|
IncompatibleTypesImpl(
|
||||||
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a),
|
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a),
|
||||||
|
|||||||
+4
@@ -1435,6 +1435,10 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
|||||||
override val diagnosticClass get() = DynamicUpperBound::class
|
override val diagnosticClass get() = DynamicUpperBound::class
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract class DynamicReceiverNotAllowed : KtFirDiagnostic<KtElement>() {
|
||||||
|
override val diagnosticClass get() = DynamicReceiverNotAllowed::class
|
||||||
|
}
|
||||||
|
|
||||||
abstract class IncompatibleTypes : KtFirDiagnostic<KtElement>() {
|
abstract class IncompatibleTypes : KtFirDiagnostic<KtElement>() {
|
||||||
override val diagnosticClass get() = IncompatibleTypes::class
|
override val diagnosticClass get() = IncompatibleTypes::class
|
||||||
abstract val typeA: KtType
|
abstract val typeA: KtType
|
||||||
|
|||||||
+5
@@ -1727,6 +1727,11 @@ internal class DynamicUpperBoundImpl(
|
|||||||
override val token: KtLifetimeToken,
|
override val token: KtLifetimeToken,
|
||||||
) : KtFirDiagnostic.DynamicUpperBound(), KtAbstractFirDiagnostic<KtTypeReference>
|
) : KtFirDiagnostic.DynamicUpperBound(), KtAbstractFirDiagnostic<KtTypeReference>
|
||||||
|
|
||||||
|
internal class DynamicReceiverNotAllowedImpl(
|
||||||
|
override val firDiagnostic: KtPsiDiagnostic,
|
||||||
|
override val token: KtLifetimeToken,
|
||||||
|
) : KtFirDiagnostic.DynamicReceiverNotAllowed(), KtAbstractFirDiagnostic<KtElement>
|
||||||
|
|
||||||
internal class IncompatibleTypesImpl(
|
internal class IncompatibleTypesImpl(
|
||||||
override val typeA: KtType,
|
override val typeA: KtType,
|
||||||
override val typeB: KtType,
|
override val typeB: KtType,
|
||||||
|
|||||||
+2
@@ -674,6 +674,8 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
|||||||
|
|
||||||
val DYNAMIC_UPPER_BOUND by error<KtTypeReference>()
|
val DYNAMIC_UPPER_BOUND by error<KtTypeReference>()
|
||||||
|
|
||||||
|
val DYNAMIC_RECEIVER_NOT_ALLOWED by error<KtElement>()
|
||||||
|
|
||||||
val INCOMPATIBLE_TYPES by error<KtElement> {
|
val INCOMPATIBLE_TYPES by error<KtElement> {
|
||||||
parameter<ConeKotlinType>("typeA")
|
parameter<ConeKotlinType>("typeA")
|
||||||
parameter<ConeKotlinType>("typeB")
|
parameter<ConeKotlinType>("typeB")
|
||||||
|
|||||||
@@ -417,6 +417,7 @@ object FirErrors {
|
|||||||
val DEPRECATED_TYPE_PARAMETER_SYNTAX by error0<KtDeclaration>(SourceElementPositioningStrategies.TYPE_PARAMETERS_LIST)
|
val DEPRECATED_TYPE_PARAMETER_SYNTAX by error0<KtDeclaration>(SourceElementPositioningStrategies.TYPE_PARAMETERS_LIST)
|
||||||
val MISPLACED_TYPE_PARAMETER_CONSTRAINTS by warning0<KtTypeParameter>()
|
val MISPLACED_TYPE_PARAMETER_CONSTRAINTS by warning0<KtTypeParameter>()
|
||||||
val DYNAMIC_UPPER_BOUND by error0<KtTypeReference>()
|
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 by error2<KtElement, ConeKotlinType, ConeKotlinType>()
|
||||||
val INCOMPATIBLE_TYPES_WARNING by warning2<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)
|
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(
|
get() = setOf(
|
||||||
FirKClassWithIncorrectTypeArgumentChecker,
|
FirKClassWithIncorrectTypeArgumentChecker,
|
||||||
FirImplicitNothingReturnTypeChecker,
|
FirImplicitNothingReturnTypeChecker,
|
||||||
|
FirDynamicReceiverChecker,
|
||||||
)
|
)
|
||||||
|
|
||||||
override val functionCheckers: Set<FirFunctionChecker>
|
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.DIVISION_BY_ZERO
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DSL_SCOPE_VIOLATION
|
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.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.DYNAMIC_UPPER_BOUND
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ELSE_MISPLACED_IN_WHEN
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ELSE_MISPLACED_IN_WHEN
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EMPTY_CHARACTER_LITERAL
|
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_UPPER_BOUND, "Dynamic type can not be used as an upper bound")
|
||||||
|
|
||||||
|
map.put(DYNAMIC_RECEIVER_NOT_ALLOWED, "Dynamic receiver is prohibited")
|
||||||
|
|
||||||
// Reflection
|
// Reflection
|
||||||
map.put(
|
map.put(
|
||||||
EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED,
|
EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED,
|
||||||
|
|||||||
+1
-1
@@ -20,7 +20,7 @@ public class J {
|
|||||||
import p.*
|
import p.*
|
||||||
|
|
||||||
class K: J.C() {
|
class K: J.C() {
|
||||||
fun <!UNSUPPORTED!>dynamic<!>.test() {
|
fun <!DYNAMIC_RECEIVER_NOT_ALLOWED, UNSUPPORTED!>dynamic<!>.test() {
|
||||||
sam(null)
|
sam(null)
|
||||||
sam(
|
sam(
|
||||||
name = null,
|
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 X1
|
||||||
object X2
|
object X2
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -41,7 +41,7 @@ fun testReassignmentWithStaticCalls(d: dynamic) {
|
|||||||
val Any.onAnyVal: Int get() = 1
|
val Any.onAnyVal: Int get() = 1
|
||||||
val Any?.onNullableAnyVal: Int get() = 1
|
val Any?.onNullableAnyVal: Int get() = 1
|
||||||
val String.onStringVal: 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 {
|
class C {
|
||||||
fun test(d: dynamic) {
|
fun test(d: dynamic) {
|
||||||
|
|||||||
+1
-1
@@ -47,7 +47,7 @@ var String.onStringVar: Int
|
|||||||
get() = 1
|
get() = 1
|
||||||
set(v) {}
|
set(v) {}
|
||||||
|
|
||||||
var dynamic.onDynamicVar: Int
|
var <!DYNAMIC_RECEIVER_NOT_ALLOWED!>dynamic<!>.onDynamicVar: Int
|
||||||
get() = 1
|
get() = 1
|
||||||
set(v) {}
|
set(v) {}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -25,7 +25,7 @@ fun test(d: dynamic) {
|
|||||||
fun Any.onAny() {}
|
fun Any.onAny() {}
|
||||||
fun Any?.onNullableAny() {}
|
fun Any?.onNullableAny() {}
|
||||||
fun String.onString() {}
|
fun String.onString() {}
|
||||||
fun dynamic.onDynamic() {}
|
fun <!DYNAMIC_RECEIVER_NOT_ALLOWED!>dynamic<!>.onDynamic() {}
|
||||||
|
|
||||||
class C {
|
class C {
|
||||||
fun test(d: dynamic) {
|
fun test(d: dynamic) {
|
||||||
|
|||||||
+7
-7
@@ -11,7 +11,7 @@ fun test(d: dynamic) {
|
|||||||
d.<!DEBUG_INFO_DYNAMIC!>varOnDynamic<!> = 1
|
d.<!DEBUG_INFO_DYNAMIC!>varOnDynamic<!> = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
fun dynamic.extTest() {
|
fun <!DYNAMIC_RECEIVER_NOT_ALLOWED!>dynamic<!>.extTest() {
|
||||||
<!DEBUG_INFO_DYNAMIC!>onDynamic<!>()
|
<!DEBUG_INFO_DYNAMIC!>onDynamic<!>()
|
||||||
<!DEBUG_INFO_DYNAMIC!>onNullableDynamic<!>()
|
<!DEBUG_INFO_DYNAMIC!>onNullableDynamic<!>()
|
||||||
|
|
||||||
@@ -32,12 +32,12 @@ fun dynamic.extTest() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun dynamic.onDynamic() {}
|
fun <!DYNAMIC_RECEIVER_NOT_ALLOWED!>dynamic<!>.onDynamic() {}
|
||||||
fun dynamic?.onNullableDynamic() {}
|
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
|
get() = 1
|
||||||
set(v) {}
|
set(v) {}
|
||||||
|
|
||||||
@@ -51,8 +51,8 @@ class ForMemberExtensions {
|
|||||||
d.<!DEBUG_INFO_DYNAMIC!>memberExtensionVal<!> = 1
|
d.<!DEBUG_INFO_DYNAMIC!>memberExtensionVal<!> = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
val dynamic.memberExtensionVal: Int get() = 1
|
val <!DYNAMIC_RECEIVER_NOT_ALLOWED!>dynamic<!>.memberExtensionVal: Int get() = 1
|
||||||
var dynamic.memberExtensionVar: Int
|
var <!DYNAMIC_RECEIVER_NOT_ALLOWED!>dynamic<!>.memberExtensionVar: Int
|
||||||
get() = 1
|
get() = 1
|
||||||
set(v) {}
|
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() {
|
fun <!DYNAMIC_RECEIVER_NOT_ALLOWED!>dynamic<!>.test() {
|
||||||
val v1 = foo()
|
val v1 = foo()
|
||||||
v1.isDynamic() // to check that anything is resolvable
|
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
|
// !MARK_DYNAMIC_CALLS
|
||||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||||
|
|
||||||
|
|||||||
Vendored
+2
-2
@@ -1,7 +1,7 @@
|
|||||||
// !MARK_DYNAMIC_CALLS
|
// !MARK_DYNAMIC_CALLS
|
||||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||||
|
|
||||||
fun dynamic.test() {
|
fun <!DYNAMIC_RECEIVER_NOT_ALLOWED!>dynamic<!>.test() {
|
||||||
<!DEBUG_INFO_DYNAMIC!>foo<!>()
|
<!DEBUG_INFO_DYNAMIC!>foo<!>()
|
||||||
<!DEBUG_INFO_DYNAMIC!>ext<!>()
|
<!DEBUG_INFO_DYNAMIC!>ext<!>()
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@ class C {
|
|||||||
|
|
||||||
val withInvoke = WithInvoke()
|
val withInvoke = WithInvoke()
|
||||||
|
|
||||||
fun dynamic.test() {
|
fun <!DYNAMIC_RECEIVER_NOT_ALLOWED!>dynamic<!>.test() {
|
||||||
s()
|
s()
|
||||||
this()
|
this()
|
||||||
|
|
||||||
|
|||||||
@@ -149,6 +149,7 @@ object StandardClassIds {
|
|||||||
val DeprecatedSinceKotlin = "DeprecatedSinceKotlin".baseId()
|
val DeprecatedSinceKotlin = "DeprecatedSinceKotlin".baseId()
|
||||||
|
|
||||||
val HidesMembers = "HidesMembers".internalId()
|
val HidesMembers = "HidesMembers".internalId()
|
||||||
|
val DynamicExtension = "DynamicExtension".internalId()
|
||||||
|
|
||||||
val Retention = "Retention".annotationId()
|
val Retention = "Retention".annotationId()
|
||||||
val Target = "Target".annotationId()
|
val Target = "Target".annotationId()
|
||||||
|
|||||||
Reference in New Issue
Block a user