[FIR JS] Implement FirJsExternalChecker

The JsAllowValueClassesInExternals feature is enabled explicitly,
because otherwise it's enabled
implicitly depending on the backend. See:
org/jetbrains/kotlin/test/builders/LanguageVersionSettingsBuilder.kt:90

A property may have a fake source return kind, while its accessor
has a real source kind. In this case we can't "just copy"
the property return type down to the accessor.
This commit is contained in:
Nikolay Lunyak
2023-01-04 16:42:00 +02:00
committed by Space Team
parent 7b8f5f9980
commit a20e29e8b7
54 changed files with 758 additions and 456 deletions
@@ -4685,6 +4685,109 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token,
)
}
add(FirJsErrors.EXTERNAL_CLASS_CONSTRUCTOR_PROPERTY_PARAMETER) { firDiagnostic ->
ExternalClassConstructorPropertyParameterImpl(
firDiagnostic as KtPsiDiagnostic,
token,
)
}
add(FirJsErrors.EXTERNAL_ENUM_ENTRY_WITH_BODY) { firDiagnostic ->
ExternalEnumEntryWithBodyImpl(
firDiagnostic as KtPsiDiagnostic,
token,
)
}
add(FirJsErrors.EXTERNAL_ANONYMOUS_INITIALIZER) { firDiagnostic ->
ExternalAnonymousInitializerImpl(
firDiagnostic as KtPsiDiagnostic,
token,
)
}
add(FirJsErrors.EXTERNAL_DELEGATION) { firDiagnostic ->
ExternalDelegationImpl(
firDiagnostic as KtPsiDiagnostic,
token,
)
}
add(FirJsErrors.EXTERNAL_DELEGATED_CONSTRUCTOR_CALL) { firDiagnostic ->
ExternalDelegatedConstructorCallImpl(
firDiagnostic as KtPsiDiagnostic,
token,
)
}
add(FirJsErrors.WRONG_BODY_OF_EXTERNAL_DECLARATION) { firDiagnostic ->
WrongBodyOfExternalDeclarationImpl(
firDiagnostic as KtPsiDiagnostic,
token,
)
}
add(FirJsErrors.WRONG_INITIALIZER_OF_EXTERNAL_DECLARATION) { firDiagnostic ->
WrongInitializerOfExternalDeclarationImpl(
firDiagnostic as KtPsiDiagnostic,
token,
)
}
add(FirJsErrors.WRONG_DEFAULT_VALUE_FOR_EXTERNAL_FUN_PARAMETER) { firDiagnostic ->
WrongDefaultValueForExternalFunParameterImpl(
firDiagnostic as KtPsiDiagnostic,
token,
)
}
add(FirJsErrors.NESTED_EXTERNAL_DECLARATION) { firDiagnostic ->
NestedExternalDeclarationImpl(
firDiagnostic as KtPsiDiagnostic,
token,
)
}
add(FirJsErrors.WRONG_EXTERNAL_DECLARATION) { firDiagnostic ->
WrongExternalDeclarationImpl(
firDiagnostic.a,
firDiagnostic as KtPsiDiagnostic,
token,
)
}
add(FirJsErrors.NESTED_CLASS_IN_EXTERNAL_INTERFACE) { firDiagnostic ->
NestedClassInExternalInterfaceImpl(
firDiagnostic as KtPsiDiagnostic,
token,
)
}
add(FirJsErrors.EXTERNAL_TYPE_EXTENDS_NON_EXTERNAL_TYPE) { firDiagnostic ->
ExternalTypeExtendsNonExternalTypeImpl(
firDiagnostic as KtPsiDiagnostic,
token,
)
}
add(FirJsErrors.INLINE_EXTERNAL_DECLARATION) { firDiagnostic ->
InlineExternalDeclarationImpl(
firDiagnostic as KtPsiDiagnostic,
token,
)
}
add(FirJsErrors.INLINE_CLASS_IN_EXTERNAL_DECLARATION_WARNING) { firDiagnostic ->
InlineClassInExternalDeclarationWarningImpl(
firDiagnostic as KtPsiDiagnostic,
token,
)
}
add(FirJsErrors.INLINE_CLASS_IN_EXTERNAL_DECLARATION) { firDiagnostic ->
InlineClassInExternalDeclarationImpl(
firDiagnostic as KtPsiDiagnostic,
token,
)
}
add(FirJsErrors.EXTENSION_FUNCTION_IN_EXTERNAL_DECLARATION) { firDiagnostic ->
ExtensionFunctionInExternalDeclarationImpl(
firDiagnostic as KtPsiDiagnostic,
token,
)
}
add(FirJsErrors.NON_ABSTRACT_MEMBER_OF_EXTERNAL_INTERFACE) { firDiagnostic ->
NonAbstractMemberOfExternalInterfaceImpl(
firDiagnostic as KtPsiDiagnostic,
token,
)
}
add(FirJsErrors.DELEGATION_BY_DYNAMIC) { firDiagnostic ->
DelegationByDynamicImpl(
firDiagnostic as KtPsiDiagnostic,
@@ -3258,6 +3258,75 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
override val diagnosticClass get() = CallToDefinedExternallyFromNonExternalDeclaration::class
}
abstract class ExternalClassConstructorPropertyParameter : KtFirDiagnostic<KtParameter>() {
override val diagnosticClass get() = ExternalClassConstructorPropertyParameter::class
}
abstract class ExternalEnumEntryWithBody : KtFirDiagnostic<KtElement>() {
override val diagnosticClass get() = ExternalEnumEntryWithBody::class
}
abstract class ExternalAnonymousInitializer : KtFirDiagnostic<KtAnonymousInitializer>() {
override val diagnosticClass get() = ExternalAnonymousInitializer::class
}
abstract class ExternalDelegation : KtFirDiagnostic<KtElement>() {
override val diagnosticClass get() = ExternalDelegation::class
}
abstract class ExternalDelegatedConstructorCall : KtFirDiagnostic<KtElement>() {
override val diagnosticClass get() = ExternalDelegatedConstructorCall::class
}
abstract class WrongBodyOfExternalDeclaration : KtFirDiagnostic<KtElement>() {
override val diagnosticClass get() = WrongBodyOfExternalDeclaration::class
}
abstract class WrongInitializerOfExternalDeclaration : KtFirDiagnostic<KtElement>() {
override val diagnosticClass get() = WrongInitializerOfExternalDeclaration::class
}
abstract class WrongDefaultValueForExternalFunParameter : KtFirDiagnostic<KtElement>() {
override val diagnosticClass get() = WrongDefaultValueForExternalFunParameter::class
}
abstract class NestedExternalDeclaration : KtFirDiagnostic<KtExpression>() {
override val diagnosticClass get() = NestedExternalDeclaration::class
}
abstract class WrongExternalDeclaration : KtFirDiagnostic<KtExpression>() {
override val diagnosticClass get() = WrongExternalDeclaration::class
abstract val classKind: String
}
abstract class NestedClassInExternalInterface : KtFirDiagnostic<KtExpression>() {
override val diagnosticClass get() = NestedClassInExternalInterface::class
}
abstract class ExternalTypeExtendsNonExternalType : KtFirDiagnostic<KtElement>() {
override val diagnosticClass get() = ExternalTypeExtendsNonExternalType::class
}
abstract class InlineExternalDeclaration : KtFirDiagnostic<KtDeclaration>() {
override val diagnosticClass get() = InlineExternalDeclaration::class
}
abstract class InlineClassInExternalDeclarationWarning : KtFirDiagnostic<KtElement>() {
override val diagnosticClass get() = InlineClassInExternalDeclarationWarning::class
}
abstract class InlineClassInExternalDeclaration : KtFirDiagnostic<KtElement>() {
override val diagnosticClass get() = InlineClassInExternalDeclaration::class
}
abstract class ExtensionFunctionInExternalDeclaration : KtFirDiagnostic<KtElement>() {
override val diagnosticClass get() = ExtensionFunctionInExternalDeclaration::class
}
abstract class NonAbstractMemberOfExternalInterface : KtFirDiagnostic<KtExpression>() {
override val diagnosticClass get() = NonAbstractMemberOfExternalInterface::class
}
abstract class DelegationByDynamic : KtFirDiagnostic<KtElement>() {
override val diagnosticClass get() = DelegationByDynamic::class
}
@@ -3942,6 +3942,92 @@ internal class CallToDefinedExternallyFromNonExternalDeclarationImpl(
override val token: KtLifetimeToken,
) : KtFirDiagnostic.CallToDefinedExternallyFromNonExternalDeclaration(), KtAbstractFirDiagnostic<PsiElement>
internal class ExternalClassConstructorPropertyParameterImpl(
override val firDiagnostic: KtPsiDiagnostic,
override val token: KtLifetimeToken,
) : KtFirDiagnostic.ExternalClassConstructorPropertyParameter(), KtAbstractFirDiagnostic<KtParameter>
internal class ExternalEnumEntryWithBodyImpl(
override val firDiagnostic: KtPsiDiagnostic,
override val token: KtLifetimeToken,
) : KtFirDiagnostic.ExternalEnumEntryWithBody(), KtAbstractFirDiagnostic<KtElement>
internal class ExternalAnonymousInitializerImpl(
override val firDiagnostic: KtPsiDiagnostic,
override val token: KtLifetimeToken,
) : KtFirDiagnostic.ExternalAnonymousInitializer(), KtAbstractFirDiagnostic<KtAnonymousInitializer>
internal class ExternalDelegationImpl(
override val firDiagnostic: KtPsiDiagnostic,
override val token: KtLifetimeToken,
) : KtFirDiagnostic.ExternalDelegation(), KtAbstractFirDiagnostic<KtElement>
internal class ExternalDelegatedConstructorCallImpl(
override val firDiagnostic: KtPsiDiagnostic,
override val token: KtLifetimeToken,
) : KtFirDiagnostic.ExternalDelegatedConstructorCall(), KtAbstractFirDiagnostic<KtElement>
internal class WrongBodyOfExternalDeclarationImpl(
override val firDiagnostic: KtPsiDiagnostic,
override val token: KtLifetimeToken,
) : KtFirDiagnostic.WrongBodyOfExternalDeclaration(), KtAbstractFirDiagnostic<KtElement>
internal class WrongInitializerOfExternalDeclarationImpl(
override val firDiagnostic: KtPsiDiagnostic,
override val token: KtLifetimeToken,
) : KtFirDiagnostic.WrongInitializerOfExternalDeclaration(), KtAbstractFirDiagnostic<KtElement>
internal class WrongDefaultValueForExternalFunParameterImpl(
override val firDiagnostic: KtPsiDiagnostic,
override val token: KtLifetimeToken,
) : KtFirDiagnostic.WrongDefaultValueForExternalFunParameter(), KtAbstractFirDiagnostic<KtElement>
internal class NestedExternalDeclarationImpl(
override val firDiagnostic: KtPsiDiagnostic,
override val token: KtLifetimeToken,
) : KtFirDiagnostic.NestedExternalDeclaration(), KtAbstractFirDiagnostic<KtExpression>
internal class WrongExternalDeclarationImpl(
override val classKind: String,
override val firDiagnostic: KtPsiDiagnostic,
override val token: KtLifetimeToken,
) : KtFirDiagnostic.WrongExternalDeclaration(), KtAbstractFirDiagnostic<KtExpression>
internal class NestedClassInExternalInterfaceImpl(
override val firDiagnostic: KtPsiDiagnostic,
override val token: KtLifetimeToken,
) : KtFirDiagnostic.NestedClassInExternalInterface(), KtAbstractFirDiagnostic<KtExpression>
internal class ExternalTypeExtendsNonExternalTypeImpl(
override val firDiagnostic: KtPsiDiagnostic,
override val token: KtLifetimeToken,
) : KtFirDiagnostic.ExternalTypeExtendsNonExternalType(), KtAbstractFirDiagnostic<KtElement>
internal class InlineExternalDeclarationImpl(
override val firDiagnostic: KtPsiDiagnostic,
override val token: KtLifetimeToken,
) : KtFirDiagnostic.InlineExternalDeclaration(), KtAbstractFirDiagnostic<KtDeclaration>
internal class InlineClassInExternalDeclarationWarningImpl(
override val firDiagnostic: KtPsiDiagnostic,
override val token: KtLifetimeToken,
) : KtFirDiagnostic.InlineClassInExternalDeclarationWarning(), KtAbstractFirDiagnostic<KtElement>
internal class InlineClassInExternalDeclarationImpl(
override val firDiagnostic: KtPsiDiagnostic,
override val token: KtLifetimeToken,
) : KtFirDiagnostic.InlineClassInExternalDeclaration(), KtAbstractFirDiagnostic<KtElement>
internal class ExtensionFunctionInExternalDeclarationImpl(
override val firDiagnostic: KtPsiDiagnostic,
override val token: KtLifetimeToken,
) : KtFirDiagnostic.ExtensionFunctionInExternalDeclaration(), KtAbstractFirDiagnostic<KtElement>
internal class NonAbstractMemberOfExternalInterfaceImpl(
override val firDiagnostic: KtPsiDiagnostic,
override val token: KtLifetimeToken,
) : KtFirDiagnostic.NonAbstractMemberOfExternalInterface(), KtAbstractFirDiagnostic<KtExpression>
internal class DelegationByDynamicImpl(
override val firDiagnostic: KtPsiDiagnostic,
override val token: KtLifetimeToken,
@@ -11,8 +11,7 @@ import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.DiagnosticL
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.PositioningStrategy
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.*
@Suppress("UNUSED_VARIABLE", "LocalVariableName", "ClassName", "unused")
@OptIn(PrivateForInline::class)
@@ -42,6 +41,25 @@ object JS_DIAGNOSTICS_LIST : DiagnosticList("FirJsErrors") {
parameter<FirNamedFunctionSymbol>("function")
}
val CALL_TO_DEFINED_EXTERNALLY_FROM_NON_EXTERNAL_DECLARATION by error<PsiElement>()
val EXTERNAL_CLASS_CONSTRUCTOR_PROPERTY_PARAMETER by error<KtParameter>()
val EXTERNAL_ENUM_ENTRY_WITH_BODY by error<KtElement>()
val EXTERNAL_ANONYMOUS_INITIALIZER by error<KtAnonymousInitializer>()
val EXTERNAL_DELEGATION by error<KtElement>()
val EXTERNAL_DELEGATED_CONSTRUCTOR_CALL by error<KtElement>()
val WRONG_BODY_OF_EXTERNAL_DECLARATION by error<KtElement>()
val WRONG_INITIALIZER_OF_EXTERNAL_DECLARATION by error<KtElement>()
val WRONG_DEFAULT_VALUE_FOR_EXTERNAL_FUN_PARAMETER by error<KtElement>()
val NESTED_EXTERNAL_DECLARATION by error<KtExpression>(PositioningStrategy.DECLARATION_SIGNATURE_OR_DEFAULT)
val WRONG_EXTERNAL_DECLARATION by error<KtExpression>(PositioningStrategy.DECLARATION_SIGNATURE_OR_DEFAULT) {
parameter<String>("classKind")
}
val NESTED_CLASS_IN_EXTERNAL_INTERFACE by error<KtExpression>(PositioningStrategy.DECLARATION_SIGNATURE_OR_DEFAULT)
val EXTERNAL_TYPE_EXTENDS_NON_EXTERNAL_TYPE by error<KtElement>(PositioningStrategy.DECLARATION_SIGNATURE_OR_DEFAULT)
val INLINE_EXTERNAL_DECLARATION by error<KtDeclaration>(PositioningStrategy.DECLARATION_SIGNATURE_OR_DEFAULT)
val INLINE_CLASS_IN_EXTERNAL_DECLARATION_WARNING by warning<KtElement>(PositioningStrategy.DECLARATION_SIGNATURE_OR_DEFAULT)
val INLINE_CLASS_IN_EXTERNAL_DECLARATION by error<KtElement>(PositioningStrategy.DECLARATION_SIGNATURE_OR_DEFAULT)
val EXTENSION_FUNCTION_IN_EXTERNAL_DECLARATION by error<KtElement>(PositioningStrategy.DECLARATION_SIGNATURE_OR_DEFAULT)
val NON_ABSTRACT_MEMBER_OF_EXTERNAL_INTERFACE by error<KtExpression>(PositioningStrategy.DECLARATION_SIGNATURE_OR_DEFAULT)
}
val DYNAMICS by object : DiagnosticGroup("Dynamics") {
@@ -12,8 +12,12 @@ import org.jetbrains.kotlin.diagnostics.rendering.RootDiagnosticRendererFactory
import org.jetbrains.kotlin.fir.analysis.diagnostics.*
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.psi.KtAnonymousInitializer
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtParameter
/*
* This file was generated automatically
@@ -39,6 +43,23 @@ object FirJsErrors {
val OVERRIDING_EXTERNAL_FUN_WITH_OPTIONAL_PARAMS by error0<KtElement>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT)
val OVERRIDING_EXTERNAL_FUN_WITH_OPTIONAL_PARAMS_WITH_FAKE by error1<KtElement, FirNamedFunctionSymbol>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT)
val CALL_TO_DEFINED_EXTERNALLY_FROM_NON_EXTERNAL_DECLARATION by error0<PsiElement>()
val EXTERNAL_CLASS_CONSTRUCTOR_PROPERTY_PARAMETER by error0<KtParameter>()
val EXTERNAL_ENUM_ENTRY_WITH_BODY by error0<KtElement>()
val EXTERNAL_ANONYMOUS_INITIALIZER by error0<KtAnonymousInitializer>()
val EXTERNAL_DELEGATION by error0<KtElement>()
val EXTERNAL_DELEGATED_CONSTRUCTOR_CALL by error0<KtElement>()
val WRONG_BODY_OF_EXTERNAL_DECLARATION by error0<KtElement>()
val WRONG_INITIALIZER_OF_EXTERNAL_DECLARATION by error0<KtElement>()
val WRONG_DEFAULT_VALUE_FOR_EXTERNAL_FUN_PARAMETER by error0<KtElement>()
val NESTED_EXTERNAL_DECLARATION by error0<KtExpression>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT)
val WRONG_EXTERNAL_DECLARATION by error1<KtExpression, String>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT)
val NESTED_CLASS_IN_EXTERNAL_INTERFACE by error0<KtExpression>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT)
val EXTERNAL_TYPE_EXTENDS_NON_EXTERNAL_TYPE by error0<KtElement>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT)
val INLINE_EXTERNAL_DECLARATION by error0<KtDeclaration>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT)
val INLINE_CLASS_IN_EXTERNAL_DECLARATION_WARNING by warning0<KtElement>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT)
val INLINE_CLASS_IN_EXTERNAL_DECLARATION by error0<KtElement>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT)
val EXTENSION_FUNCTION_IN_EXTERNAL_DECLARATION by error0<KtElement>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT)
val NON_ABSTRACT_MEMBER_OF_EXTERNAL_INTERFACE by error0<KtExpression>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT)
// Dynamics
val DELEGATION_BY_DYNAMIC by error0<KtElement>()
@@ -7,18 +7,36 @@ package org.jetbrains.kotlin.fir.analysis.diagnostics.js
import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactoryToRendererMap
import org.jetbrains.kotlin.diagnostics.rendering.BaseDiagnosticRendererFactory
import org.jetbrains.kotlin.diagnostics.rendering.CommonRenderers
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers
import org.jetbrains.kotlin.fir.analysis.diagnostics.checkMissingMessages
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.CALL_TO_DEFINED_EXTERNALLY_FROM_NON_EXTERNAL_DECLARATION
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.EXTENSION_FUNCTION_IN_EXTERNAL_DECLARATION
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.EXTERNAL_ANONYMOUS_INITIALIZER
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.EXTERNAL_CLASS_CONSTRUCTOR_PROPERTY_PARAMETER
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.EXTERNAL_DELEGATED_CONSTRUCTOR_CALL
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.EXTERNAL_DELEGATION
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.EXTERNAL_ENUM_ENTRY_WITH_BODY
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.EXTERNAL_TYPE_EXTENDS_NON_EXTERNAL_TYPE
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.DELEGATION_BY_DYNAMIC
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.IMPLEMENTING_FUNCTION_INTERFACE
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.INLINE_CLASS_IN_EXTERNAL_DECLARATION
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.INLINE_CLASS_IN_EXTERNAL_DECLARATION_WARNING
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.INLINE_EXTERNAL_DECLARATION
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.JS_MODULE_PROHIBITED_ON_NON_NATIVE
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.JS_MODULE_PROHIBITED_ON_VAR
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.NESTED_JS_MODULE_PROHIBITED
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.NESTED_CLASS_IN_EXTERNAL_INTERFACE
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.NESTED_EXTERNAL_DECLARATION
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.NON_ABSTRACT_MEMBER_OF_EXTERNAL_INTERFACE
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.OVERRIDING_EXTERNAL_FUN_WITH_OPTIONAL_PARAMS
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.OVERRIDING_EXTERNAL_FUN_WITH_OPTIONAL_PARAMS_WITH_FAKE
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.RUNTIME_ANNOTATION_NOT_SUPPORTED
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.RUNTIME_ANNOTATION_ON_EXTERNAL_DECLARATION
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.WRONG_BODY_OF_EXTERNAL_DECLARATION
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.WRONG_DEFAULT_VALUE_FOR_EXTERNAL_FUN_PARAMETER
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.WRONG_EXTERNAL_DECLARATION
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.WRONG_INITIALIZER_OF_EXTERNAL_DECLARATION
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.WRONG_JS_QUALIFIER
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.WRONG_MULTIPLE_INHERITANCE
@@ -51,6 +69,38 @@ object FirJsErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
RUNTIME_ANNOTATION_NOT_SUPPORTED,
"Reflection is not supported in JavaScript target, therefore you won't be able to read this annotation in run-time"
)
map.put(EXTERNAL_CLASS_CONSTRUCTOR_PROPERTY_PARAMETER, "External class constructor cannot have a property parameter")
map.put(EXTERNAL_ENUM_ENTRY_WITH_BODY, "Entry of external enum class can't have body")
map.put(EXTERNAL_ANONYMOUS_INITIALIZER, "Anonymous initializer is not allowed in external classes")
map.put(EXTERNAL_DELEGATION, "Can't use delegate on external declaration")
map.put(EXTERNAL_DELEGATED_CONSTRUCTOR_CALL, "Delegated constructor call in external class is not allowed")
map.put(
WRONG_BODY_OF_EXTERNAL_DECLARATION,
"Wrong body of external declaration. Must be either ' = definedExternally' or { definedExternally }"
)
map.put(WRONG_INITIALIZER_OF_EXTERNAL_DECLARATION, "Wrong initializer of external declaration. Must be ' = definedExternally'")
map.put(
WRONG_DEFAULT_VALUE_FOR_EXTERNAL_FUN_PARAMETER,
"Wrong default value for parameter of external function. Must be ' = definedExternally'"
)
map.put(NESTED_EXTERNAL_DECLARATION, "Non top-level `external` declaration")
map.put(WRONG_EXTERNAL_DECLARATION, "Declaration of such kind ({0}) can''t be external", CommonRenderers.STRING)
map.put(NESTED_CLASS_IN_EXTERNAL_INTERFACE, "Interface can't contain nested classes and objects")
map.put(EXTERNAL_TYPE_EXTENDS_NON_EXTERNAL_TYPE, "External type extends non-external type")
map.put(INLINE_EXTERNAL_DECLARATION, "Inline external declaration")
map.put(
INLINE_CLASS_IN_EXTERNAL_DECLARATION_WARNING,
"Using value classes as parameter type or return type of external declarations is experimental"
)
map.put(
INLINE_CLASS_IN_EXTERNAL_DECLARATION,
"Using value classes as parameter type or return type of external declarations is not supported"
)
map.put(EXTENSION_FUNCTION_IN_EXTERNAL_DECLARATION, "Function types with receiver are prohibited in external declarations")
map.put(
NON_ABSTRACT_MEMBER_OF_EXTERNAL_INTERFACE,
"Only nullable properties of external interfaces are allowed to be non-abstract"
)
map.checkMissingMessages(FirJsErrors)
}
@@ -24,6 +24,7 @@ object JsDeclarationCheckers : DeclarationCheckers() {
get() = setOf(
FirJsModuleChecker,
FirJsRuntimeAnnotationChecker,
FirJsExternalChecker,
)
override val classCheckers: Set<FirClassChecker>
@@ -0,0 +1,348 @@
/*
* 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.js.checkers.declaration
import org.jetbrains.kotlin.*
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactory0
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.checkers.*
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirBasicDeclarationChecker
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors
import org.jetbrains.kotlin.fir.analysis.js.checkers.isEffectivelyExternal
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyBackingField
import org.jetbrains.kotlin.fir.declarations.impl.FirPrimaryConstructor
import org.jetbrains.kotlin.fir.declarations.utils.*
import org.jetbrains.kotlin.fir.expressions.FirPropertyAccessExpression
import org.jetbrains.kotlin.fir.expressions.FirReturnExpression
import org.jetbrains.kotlin.fir.expressions.impl.FirSingleExpressionBlock
import org.jetbrains.kotlin.fir.analysis.js.checkers.isNativeObject
import org.jetbrains.kotlin.fir.references.toResolvedPropertySymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.JsStandardClassIds
import org.jetbrains.kotlin.name.JsStandardClassIds.Annotations.JsNative
import org.jetbrains.kotlin.psi.KtParameter
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
object FirJsExternalChecker : FirBasicDeclarationChecker() {
override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
if (!declaration.symbol.isNativeObject(context)) return
if (!context.isTopLevel) {
if (declaration !is FirPropertyAccessor && declaration.isDirectlyExternal(context.session)) {
reporter.reportOn(declaration.source, FirJsErrors.NESTED_EXTERNAL_DECLARATION, context)
}
}
if (declaration is FirClass) {
// TODO: KT-55600: Stop generating diagnostic
// messages inside checkers
val classKind = when {
declaration.status.isData -> "data class"
declaration.status.isInner -> "inner class"
declaration.status.isInline -> "value class"
declaration.status.isFun -> "fun interface"
declaration.classKind == ClassKind.ANNOTATION_CLASS -> "annotation class"
else -> null
}
if (classKind != null) {
reporter.reportOn(declaration.source, FirJsErrors.WRONG_EXTERNAL_DECLARATION, classKind, context)
}
}
if (declaration is FirPropertyAccessor && declaration.isDirectlyExternal(context.session)) {
reporter.reportOn(declaration.source, FirJsErrors.WRONG_EXTERNAL_DECLARATION, "property accessor", context)
} else if (declaration !is FirPrimaryConstructor && declaration.isPrivateMemberOfExternalClass(context.session)) {
reporter.reportOn(declaration.source, FirJsErrors.WRONG_EXTERNAL_DECLARATION, "private member of class", context)
}
val container = context.containingDeclarations.lastOrNull()
if (
declaration is FirClass &&
declaration.classKind != ClassKind.INTERFACE &&
container is FirClass && container.classKind == ClassKind.INTERFACE
) {
reporter.reportOn(declaration.source, FirJsErrors.NESTED_CLASS_IN_EXTERNAL_INTERFACE, context)
}
if (declaration !is FirPropertyAccessor && declaration is FirCallableDeclaration && declaration.isExtension) {
val target = when (declaration) {
is FirFunction -> "extension function"
is FirProperty -> "extension property"
else -> "extension member"
}
reporter.reportOn(declaration.source, FirJsErrors.WRONG_EXTERNAL_DECLARATION, target, context)
}
if (declaration is FirClass && declaration.classKind != ClassKind.ANNOTATION_CLASS) {
val superClasses = declaration.superInterfaces(context.session).toMutableList()
declaration.superClassNotAny(context.session)?.let {
superClasses.add(it)
}
if (declaration.classKind == ClassKind.ENUM_CLASS || declaration.classKind == ClassKind.ENUM_ENTRY) {
superClasses.removeAll { it.classId?.asSingleFqName()?.toUnsafe() == StandardNames.FqNames._enum }
}
val superDeclarations = superClasses.mapNotNull { it.toSymbol(context.session) }
if (superDeclarations.any { !it.isNativeObject(context) && it.classId.asSingleFqName() != StandardNames.FqNames.throwable }) {
reporter.reportOn(declaration.source, FirJsErrors.EXTERNAL_TYPE_EXTENDS_NON_EXTERNAL_TYPE, context)
}
}
if (declaration is FirFunction && declaration.isInline) {
reporter.reportOn(declaration.source, FirJsErrors.INLINE_EXTERNAL_DECLARATION, context)
}
fun reportOnParametersAndReturnTypesIf(
diagnosticFactory: KtDiagnosticFactory0,
condition: (ConeKotlinType) -> Boolean,
) {
if (
declaration !is FirCallableDeclaration ||
declaration is FirDefaultPropertyAccessor ||
declaration is FirDefaultPropertyBackingField
) {
return
}
fun checkTypeIsNotInlineClass(type: ConeKotlinType, elementToReport: KtSourceElement?) {
if (condition(type)) {
reporter.reportOn(elementToReport, diagnosticFactory, context)
}
}
if (declaration.returnTypeRef.source?.allowsReporting == true) {
declaration.returnTypeRef.source?.let {
checkTypeIsNotInlineClass(declaration.returnTypeRef.coneType, it)
}
}
if (declaration !is FirFunction) {
return
}
for (parameter in declaration.valueParameters) {
val ktParam = if (parameter.source?.psi is KtParameter) {
parameter.source
} else {
declaration.source
}
if (ktParam?.allowsReporting != true) {
continue
}
val typeToCheck = parameter.varargElementType ?: parameter.returnTypeRef.coneType
checkTypeIsNotInlineClass(typeToCheck, ktParam)
}
}
val valueClassInExternalDiagnostic = when {
context.languageVersionSettings.supportsFeature(LanguageFeature.JsAllowValueClassesInExternals) -> {
FirJsErrors.INLINE_CLASS_IN_EXTERNAL_DECLARATION_WARNING
}
else -> {
FirJsErrors.INLINE_CLASS_IN_EXTERNAL_DECLARATION
}
}
reportOnParametersAndReturnTypesIf(valueClassInExternalDiagnostic) { it.isValueClass(context.session) }
if (!context.languageVersionSettings.supportsFeature(LanguageFeature.JsEnableExtensionFunctionInExternals)) {
reportOnParametersAndReturnTypesIf(
FirJsErrors.EXTENSION_FUNCTION_IN_EXTERNAL_DECLARATION, ConeKotlinType::isExtensionFunctionType
)
}
if (
declaration is FirCallableDeclaration &&
declaration.isNonAbstractMemberIfInterface(context.session) &&
!declaration.isNullableProperty()
) {
reporter.reportOn(declaration.source, FirJsErrors.NON_ABSTRACT_MEMBER_OF_EXTERNAL_INTERFACE, context)
}
declaration.checkBody(context, reporter)
declaration.checkDelegation(context, reporter)
declaration.checkAnonymousInitializer(context, reporter)
declaration.checkEnumEntry(context, reporter)
declaration.checkConstructorPropertyParam(context, reporter)
}
private val KtSourceElement.allowsReporting
get() = kind !is KtFakeSourceElementKind || kind == KtFakeSourceElementKind.PropertyFromParameter
private val FirValueParameter.varargElementType
get() = when {
!isVararg -> null
else -> returnTypeRef.coneType.typeArguments.firstOrNull()?.type
}
private fun FirClass.superClassNotAny(session: FirSession) = superConeTypes
.filterNot { it.isAny || it.isNullableAny }
.find { it.toSymbol(session)?.classKind == ClassKind.CLASS }
private fun FirClass.superInterfaces(session: FirSession) = superConeTypes
.filterNot { it.isAny || it.isNullableAny }
.filter { it.toSymbol(session)?.classKind == ClassKind.INTERFACE }
private fun FirDeclaration.checkBody(context: CheckerContext, reporter: DiagnosticReporter) {
if (this is FirDefaultPropertyAccessor) return
val body = when (this) {
is FirFunction -> body
is FirAnonymousInitializer -> body
else -> null
}
val initializer = when {
this is FirEnumEntry -> null
source?.kind == KtFakeSourceElementKind.PropertyFromParameter -> null
this is FirVariable -> initializer
body is FirSingleExpressionBlock -> (body.statement as? FirReturnExpression)?.result
else -> null
}
val isWrong = body !is FirSingleExpressionBlock && !hasValidExternalBody()
|| initializer != null && !initializer.isDefinedExternallyExpression()
if (isWrong && body != null) {
reporter.reportOn(body.source, FirJsErrors.WRONG_BODY_OF_EXTERNAL_DECLARATION, context)
} else if (isWrong && initializer != null) {
reporter.reportOn(initializer.source, FirJsErrors.WRONG_INITIALIZER_OF_EXTERNAL_DECLARATION, context)
}
// we shouldn't check such things as the
// copy() function of a data class
if (source?.kind !is KtRealSourceElementKind) {
return
}
if (this is FirFunction) {
for (defaultValue in valueParameters.mapNotNull { it.defaultValue }) {
if (!defaultValue.isDefinedExternallyExpression()) {
reporter.reportOn(defaultValue.source, FirJsErrors.WRONG_DEFAULT_VALUE_FOR_EXTERNAL_FUN_PARAMETER, context)
}
}
}
}
private fun FirDeclaration.checkDelegation(context: CheckerContext, reporter: DiagnosticReporter) {
if (this !is FirMemberDeclaration || !symbol.isEffectivelyExternal(context)) return
if (this is FirClass) {
declarations.firstIsInstanceOrNull<FirPrimaryConstructor>()?.let {
val constructorCall = it.delegatedConstructor
if (constructorCall?.source?.kind is KtRealSourceElementKind) {
reporter.reportOn(constructorCall.source, FirJsErrors.EXTERNAL_DELEGATED_CONSTRUCTOR_CALL, context)
}
}
for ((superType, delegate) in collectSupertypesWithDelegates()) {
when {
delegate != null -> {
reporter.reportOn(superType.source, FirJsErrors.EXTERNAL_DELEGATION, context)
}
}
}
} else if (this is FirConstructor && !isPrimary) {
val delegationCall = delegatedConstructor
if (delegationCall?.source?.kind is KtRealSourceElementKind) {
reporter.reportOn(delegationCall.source, FirJsErrors.EXTERNAL_DELEGATED_CONSTRUCTOR_CALL, context)
}
} else if (this is FirProperty) {
delegate?.let {
reporter.reportOn(it.source, FirJsErrors.EXTERNAL_DELEGATION, context)
}
}
}
private fun FirDeclaration.checkAnonymousInitializer(context: CheckerContext, reporter: DiagnosticReporter) {
if (this !is FirClass) return
for (anonymousInitializer in anonymousInitializers) {
reporter.reportOn(anonymousInitializer.source, FirJsErrors.EXTERNAL_ANONYMOUS_INITIALIZER, context)
}
}
private fun FirDeclaration.checkEnumEntry(context: CheckerContext, reporter: DiagnosticReporter) {
if (this !is FirEnumEntry) return
initializer?.let {
reporter.reportOn(it.source, FirJsErrors.EXTERNAL_ENUM_ENTRY_WITH_BODY, context)
}
}
private fun FirDeclaration.checkConstructorPropertyParam(context: CheckerContext, reporter: DiagnosticReporter) {
if (this !is FirProperty || source?.kind != KtFakeSourceElementKind.PropertyFromParameter) return
val containingClass = getContainingClassSymbol(context.session) as? FirClassSymbol<*> ?: return
if (containingClass.isData || containingClass.classKind == ClassKind.ANNOTATION_CLASS) return
reporter.reportOn(source, FirJsErrors.EXTERNAL_CLASS_CONSTRUCTOR_PROPERTY_PARAMETER, context)
}
private fun FirDeclaration.isDirectlyExternal(session: FirSession): Boolean {
// source kind is checked, otherwise this function
// may return true for a primary constructor of an external class
if (this is FirDefaultPropertyAccessor || this.source?.kind !is KtRealSourceElementKind) return false
return hasModifier(KtTokens.EXTERNAL_KEYWORD) || hasAnnotation(JsNative, session)
}
private fun FirDeclaration.isPrivateMemberOfExternalClass(session: FirSession): Boolean {
if (this is FirPropertyAccessor && visibility == propertySymbol.visibility) return false
if (this !is FirMemberDeclaration || visibility != Visibilities.Private) return false
val containingDeclaration = getContainingClassSymbol(session) ?: return false
return containingDeclaration.isNativeObject(session)
}
private fun FirDeclaration.isNonAbstractMemberIfInterface(session: FirSession): Boolean {
return this is FirCallableDeclaration
&& modality != Modality.ABSTRACT
&& (getContainingClassSymbol(session) as? FirClassSymbol<*>)?.classKind == ClassKind.INTERFACE
&& this !is FirPropertyAccessor
}
private fun FirCallableDeclaration.isNullableProperty() = this is FirProperty && returnTypeRef.coneType.isNullable
private fun FirDeclaration.hasValidExternalBody(): Boolean {
val body = when (this) {
is FirFunction -> body
is FirAnonymousInitializer -> body
else -> return true
}
return when {
body is FirSingleExpressionBlock -> body.isDefinedExternallyExpression()
body != null -> {
val statement = body.statements.singleOrNull() ?: return false
statement.isDefinedExternallyExpression()
}
else -> false
}
}
private fun FirElement.isDefinedExternallyExpression(): Boolean {
val declaration = (this as? FirPropertyAccessExpression)
?.calleeReference?.toResolvedPropertySymbol() ?: return false
return declaration.callableId in JsStandardClassIds.Callables.definedExternallyPropertyNames
}
}
@@ -206,6 +206,11 @@ fun FirNamedFunctionSymbol.overriddenFunctions(
return overriddenFunctions
}
fun FirClass.collectSupertypesWithDelegates(): Map<FirTypeRef, FirFieldSymbol?> {
val fieldsMap = delegateFieldsMap ?: emptyMap()
return superTypeRefs.mapIndexed { index, it -> it to fieldsMap[index] }.toMap()
}
/**
* Returns the modality of the class
*/
@@ -1120,7 +1120,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
source = parameterSource?.fakeElement(KtFakeSourceElementKind.DataClassGeneratedMembers)
moduleData = baseModuleData
origin = FirDeclarationOrigin.Source
returnTypeRef = firProperty.returnTypeRef
returnTypeRef = firProperty.returnTypeRef.copyWithNewSourceKind(KtFakeSourceElementKind.DataClassGeneratedMembers)
this.name = name
status = FirDeclarationStatusImpl(Visibilities.Public, Modality.FINAL).apply {
isOperator = true
@@ -443,13 +443,13 @@ open class FirDeclarationsResolveTransformer(transformer: FirAbstractBodyResolve
when {
isGetter -> {
if (returnTypeRef is FirImplicitTypeRef || forceUpdateForNonImplicitTypes) {
replaceReturnTypeRef(propertyTypeRef)
replaceReturnTypeRef(propertyTypeRef.copyWithNewSource(returnTypeRef.source))
}
}
isSetter -> {
val valueParameter = valueParameters.firstOrNull() ?: return
if (valueParameter.returnTypeRef is FirImplicitTypeRef) {
valueParameter.replaceReturnTypeRef(propertyTypeRef)
valueParameter.replaceReturnTypeRef(propertyTypeRef.copyWithNewSource(returnTypeRef.source))
}
}
}
@@ -6,12 +6,9 @@
package org.jetbrains.kotlin.fir
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.KtFakeSourceElementKind
import org.jetbrains.kotlin.KtPsiSourceElement
import org.jetbrains.kotlin.KtRealPsiSourceElement
import org.jetbrains.kotlin.*
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.fakeElement
import org.jetbrains.kotlin.fir.declarations.FirContextReceiver
import org.jetbrains.kotlin.fir.declarations.FirDeclarationStatus
import org.jetbrains.kotlin.fir.declarations.FirFile
@@ -32,11 +29,15 @@ import org.jetbrains.kotlin.util.wrapIntoSourceCodeAnalysisExceptionIfNeeded
// TODO: rewrite
fun FirBlock.returnExpressions(): List<FirExpression> = listOfNotNull(statements.lastOrNull() as? FirExpression)
// do we need a deep copy here ?
fun <R : FirTypeRef> R.copyWithNewSourceKind(newKind: KtFakeSourceElementKind): R {
if (source == null) return this
if (source?.kind == newKind) return this
val newSource = source?.fakeElement(newKind)
return copyWithNewSource(source?.fakeElement(newKind))
}
// do we need a deep copy here ?
fun <R : FirTypeRef> R.copyWithNewSource(newSource: KtSourceElement?): R {
if (source?.kind == newSource?.kind) return this
@Suppress("UNCHECKED_CAST")
return when (val typeRef = this) {
@@ -63,7 +64,7 @@ fun <R : FirTypeRef> R.copyWithNewSourceKind(newKind: KtFakeSourceElementKind):
isMarkedNullable = typeRef.isMarkedNullable
annotations += typeRef.annotations
}
is FirImplicitBuiltinTypeRef -> typeRef.withFakeSource(newKind)
is FirImplicitBuiltinTypeRef -> typeRef.withNewSource(newSource)
is FirIntersectionTypeRef -> buildIntersectionTypeRef {
source = newSource
isMarkedNullable = typeRef.isMarkedNullable
@@ -43,3 +43,5 @@ val FirDeclaration.isNonLocal
is FirClassLikeDeclaration -> !symbol.classId.isLocal
else -> false
}
val FirCallableDeclaration.isExtension get() = receiverParameter != null
@@ -183,10 +183,9 @@ class FirImplicitKMutableProperty2TypeRef(
arrayOf(dispatchReceiverTypeArgument, extensionReceiverTypeArgument, propertyTypeArgument)
)
fun FirImplicitBuiltinTypeRef.withFakeSource(kind: KtFakeSourceElementKind): FirImplicitBuiltinTypeRef {
fun FirImplicitBuiltinTypeRef.withNewSource(newSource: KtSourceElement?): FirImplicitBuiltinTypeRef {
val source = source ?: return this
if (source.kind == kind) return this
val newSource = source.fakeElement(kind)
if (source.kind == newSource?.kind) return this
return when (this) {
is FirImplicitUnitTypeRef -> FirImplicitUnitTypeRef(newSource)
is FirImplicitAnyTypeRef -> FirImplicitAnyTypeRef(newSource)
@@ -1,5 +0,0 @@
external class A {
init {
definedExternally
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
external class A {
<!EXTERNAL_ANONYMOUS_INITIALIZER!>init {
definedExternally
@@ -1,30 +0,0 @@
external fun foo(): Int = definedExternally
external fun bar(): Unit {
definedExternally
}
external fun baz(): Int = 23
external fun f(x: Int, y: String = definedExternally): Unit
external fun g(x: Int, y: String = ""): Unit
external var a: Int
get() = definedExternally
set(value) {
definedExternally
}
external val b: Int
get() = 23
external val c: Int = definedExternally
external val d: Int = 23
external class C {
fun foo(): Int = definedExternally
fun bar(): Int = 23
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
external fun foo(): Int = definedExternally
external fun bar(): Unit {
@@ -27,4 +28,4 @@ external class C {
fun foo(): Int = definedExternally
fun bar(): Int = <!WRONG_BODY_OF_EXTERNAL_DECLARATION!>23<!>
}
}
@@ -1,17 +1,17 @@
// !DIAGNOSTICS: -DEBUG_INFO_MISSING_UNRESOLVED
external open class Base(x: Int) {
constructor(x: String) : this(23)
constructor(x: String) : <!EXTERNAL_DELEGATED_CONSTRUCTOR_CALL!>this<!>(23)
constructor(x: String, y: String) : this("")
constructor(x: String, y: String) : <!EXTERNAL_DELEGATED_CONSTRUCTOR_CALL!>this<!>("")
}
external open class Derived1() : Base(23) {
constructor(x: Byte) : super(23)
external open class Derived1() : <!EXTERNAL_DELEGATED_CONSTRUCTOR_CALL!>Base(23)<!> {
constructor(x: Byte) : <!EXTERNAL_DELEGATED_CONSTRUCTOR_CALL!>super<!>(23)
constructor(x: String) : super("")
constructor(x: String) : <!EXTERNAL_DELEGATED_CONSTRUCTOR_CALL!>super<!>("")
constructor(x: String, y: String) : super("")
constructor(x: String, y: String) : <!EXTERNAL_DELEGATED_CONSTRUCTOR_CALL!>super<!>("")
}
external open class Derived2() : Base("")
external open class Derived2() : <!EXTERNAL_DELEGATED_CONSTRUCTOR_CALL!>Base("")<!>
@@ -9,10 +9,10 @@ class Delegate {
operator fun setValue(thisRef: Any?, property: Any, value: String) {}
}
external class A : I by O {
val prop by Delegate()
external class A : <!EXTERNAL_DELEGATION!>I<!> by O {
val prop by <!EXTERNAL_DELEGATION!>Delegate()<!>
var mutableProp by Delegate()
var mutableProp by <!EXTERNAL_DELEGATION!>Delegate()<!>
}
external val topLevelProp by Delegate()
external val topLevelProp by <!EXTERNAL_DELEGATION!>Delegate()<!>
@@ -1,7 +1,7 @@
external enum class E {
X,
Y {
<!EXTERNAL_ENUM_ENTRY_WITH_BODY!>Y {
fun foo()
},
Z {}
},<!>
<!EXTERNAL_ENUM_ENTRY_WITH_BODY!>Z {}<!>
}
@@ -1,10 +0,0 @@
class A
external fun A.foo(): Unit = definedExternally
external var A.bar: String
get() = definedExternally
set(value) = definedExternally
external val A.baz: String
get() = definedExternally
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
class A
<!WRONG_EXTERNAL_DECLARATION!>external fun A.foo(): Unit<!> = definedExternally
@@ -1,25 +0,0 @@
external fun foo(f: Int.() -> Int)
external fun bar(vararg f: Int.() -> Int)
external fun baz(): Int.() -> Int
external val prop: Int.() -> Int
external var prop2: Int.() -> Int
external val propGet
get(): Int.() -> Int = definedExternally
external var propSet
get(): Int.() -> Int = definedExternally
set(v: Int.() -> Int) = definedExternally
external class A(f: Int.() -> Int)
external data class B(
val a: Int.() -> Int,
var b: Int.() -> Int
) {
val c: Int.() -> Int
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
external fun foo(<!EXTENSION_FUNCTION_IN_EXTERNAL_DECLARATION!>f: Int.() -> Int<!>)
external fun bar(<!EXTENSION_FUNCTION_IN_EXTERNAL_DECLARATION!>vararg f: Int.() -> Int<!>)
@@ -1,3 +0,0 @@
external fun interface I {
fun f()
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
external fun interface <!WRONG_EXTERNAL_DECLARATION!>I<!> {
fun f()
}
@@ -1,11 +0,0 @@
external interface I {
interface J
class C
object O
enum class E
companion object
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
external interface I {
interface J
@@ -1,19 +0,0 @@
open class A
interface I
external open class B
external class C : A
external class D : B, I
external interface K : I
external enum class E {
X
}
external enum class F : I {
X
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
open class A
interface I
@@ -1,19 +0,0 @@
// !DIAGNOSTICS: -NOTHING_TO_INLINE
inline external fun foo(): Unit
inline external val bar: Int
get() = definedExternally
external val baz: Int
inline get() = definedExternally
external class A {
inline fun foo(): Unit
inline val bar: Int
get() = definedExternally
val baz: Int
inline get() = definedExternally
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -NOTHING_TO_INLINE
<!INLINE_EXTERNAL_DECLARATION!>inline external fun foo(): Unit<!>
@@ -1,9 +0,0 @@
// !LANGUAGE: +InlineClasses, -JvmInlineValueClasses
external inline class C(val a: Int) {
fun foo()
}
<!WRONG_MODIFIER_TARGET!>inline<!> external enum class E {
A
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !LANGUAGE: +InlineClasses, -JvmInlineValueClasses
external inline class <!WRONG_EXTERNAL_DECLARATION!>C(<!EXTERNAL_CLASS_CONSTRUCTOR_PROPERTY_PARAMETER!>val a: Int<!>)<!> {
@@ -1,64 +0,0 @@
// !LANGUAGE: +InlineClasses, -JvmInlineValueClasses
// FILE: uint.kt
package kotlin
inline class UInt(private val i: Int)
// FILE: test.kt
inline class SomeIC(val a: Int)
external val l: SomeIC
external val ll
get(): SomeIC = definedExternally
external var r: SomeIC
external var rr: SomeIC
get() = definedExternally
set(v: SomeIC) { definedExternally }
external fun foo(): SomeIC
external fun foo(c: SomeIC): SomeIC
external fun foo(a: Int, c: SomeIC): SomeIC
external fun foo(a: Int, <!FORBIDDEN_VARARG_PARAMETER_TYPE!>vararg<!> args: SomeIC)
external fun foo(a: Int, ui: UInt, vararg args: UInt)
external class CC(
a: SomeIC,
val b: SomeIC,
var c: SomeIC
) {
val l: SomeIC
var r: SomeIC
fun foo(): SomeIC
fun foo(c: SomeIC): SomeIC
fun foo(a: Int, c: SomeIC): SomeIC
class N(
a: SomeIC,
val b: SomeIC,
var c: SomeIC
) {
val l: SomeIC
var r: SomeIC
fun foo(): SomeIC
fun foo(c: SomeIC): SomeIC
fun foo(a: Int, c: SomeIC): SomeIC
}
}
external interface EI {
val l: SomeIC
var r: SomeIC
fun foo(): SomeIC
fun foo(c: SomeIC): SomeIC
fun foo(a: Int, c: SomeIC): SomeIC
}
@@ -1,4 +1,5 @@
// !LANGUAGE: +InlineClasses, -JvmInlineValueClasses
// FIR_IDENTICAL
// !LANGUAGE: +InlineClasses, -JvmInlineValueClasses, -JsAllowValueClassesInExternals
// FILE: uint.kt
@@ -1,65 +0,0 @@
// !LANGUAGE: +InlineClasses, -JvmInlineValueClasses, +JsAllowValueClassesInExternals
// !DIAGNOSTICS: +INLINE_CLASS_IN_EXTERNAL_DECLARATION_WARNING
// FILE: uint.kt
package kotlin
inline class UInt(private val i: Int)
// FILE: test.kt
inline class SomeIC(val a: Int)
external val l: SomeIC
external val ll
get(): SomeIC = definedExternally
external var r: SomeIC
external var rr: SomeIC
get() = definedExternally
set(v: SomeIC) { definedExternally }
external fun foo(): SomeIC
external fun foo(c: SomeIC): SomeIC
external fun foo(a: Int, c: SomeIC): SomeIC
external fun foo(a: Int, <!FORBIDDEN_VARARG_PARAMETER_TYPE!>vararg<!> args: SomeIC)
external fun foo(a: Int, ui: UInt, vararg args: UInt)
external class CC(
a: SomeIC,
val b: SomeIC,
var c: SomeIC
) {
val l: SomeIC
var r: SomeIC
fun foo(): SomeIC
fun foo(c: SomeIC): SomeIC
fun foo(a: Int, c: SomeIC): SomeIC
class N(
a: SomeIC,
val b: SomeIC,
var c: SomeIC
) {
val l: SomeIC
var r: SomeIC
fun foo(): SomeIC
fun foo(c: SomeIC): SomeIC
fun foo(a: Int, c: SomeIC): SomeIC
}
}
external interface EI {
val l: SomeIC
var r: SomeIC
fun foo(): SomeIC
fun foo(c: SomeIC): SomeIC
fun foo(a: Int, c: SomeIC): SomeIC
}
@@ -1,4 +1,6 @@
// FIR_IDENTICAL
// !LANGUAGE: +InlineClasses, -JvmInlineValueClasses, +JsAllowValueClassesInExternals
// !DIAGNOSTICS: +INLINE_CLASS_IN_EXTERNAL_DECLARATION_WARNING
// FILE: uint.kt
@@ -1,9 +0,0 @@
external class C {
inner class Inner
}
external enum class E {
X;
inner class Inner
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
external class C {
inner class <!WRONG_EXTERNAL_DECLARATION!>Inner<!>
}
@@ -6,4 +7,4 @@ external enum class E {
X;
inner class <!WRONG_EXTERNAL_DECLARATION!>Inner<!>
}
}
@@ -1,41 +0,0 @@
object O
class TopLevel {
external class A
class B
fun foo() = 23
external fun bar(): Int
val x = "a"
external val y: String
val O.u: String get() = "O.u"
}
external class TopLevelNative {
external class A
class B
fun foo(): Int = definedExternally
external fun bar(): Int
val x: String = definedExternally
external val y: String
}
fun topLevelFun() {
external class A
class B
fun foo() = 23
external fun bar(): Int
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
object O
class TopLevel {
@@ -39,4 +40,3 @@ fun topLevelFun() {
<!NESTED_EXTERNAL_DECLARATION!>external fun bar(): Int<!>
}
@@ -1,21 +0,0 @@
external interface I {
fun foo(): Unit = definedExternally
val a: Int?
get() = definedExternally
var b: String?
get() = definedExternally
set(value) = definedExternally
val c: Int
get() = definedExternally
var d: String
get() = definedExternally
set(value) = definedExternally
var e: dynamic
get() = definedExternally
set(value) = definedExternally
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
external interface I {
<!NON_ABSTRACT_MEMBER_OF_EXTERNAL_INTERFACE!>fun foo(): Unit<!> = definedExternally
@@ -1,68 +0,0 @@
// !DIAGNOSTICS: -NOTHING_TO_INLINE
// TODO: should we disable NOTHING_TO_INLINE in JS backend?
// TODO: uncomment declarations in case we decide to implement KT-14031
external class C {
private fun a(): Int
private val b: String
private var c: Float
private var d: Float
get
set
var e: Float
get
private set
/*
private inline fun inline_a(): Int = 23
private inline val inline_prop: Int
get() = 42
*/
}
external object O {
private fun a(): Int
private val b: String
private var c: Float
private var d: Float
get
set
/*
private inline fun inline_a(): Int = 23
private inline val inline_prop: Int
get() = 42
*/
}
external class Outer {
class Inner {
private fun a(): Int
private val b: String
private var c: Float
private var d: Float
get
set
/*
private inline fun inline_a(): Int = 23
private inline val inline_prop: Int
get() = 42
*/
}
private class PrivateInner
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -NOTHING_TO_INLINE
// TODO: should we disable NOTHING_TO_INLINE in JS backend?
// TODO: uncomment declarations in case we decide to implement KT-14031
@@ -1 +0,0 @@
external class C(x: Int, val y: String)
@@ -1 +1,2 @@
// FIR_IDENTICAL
external class C(x: Int, <!EXTERNAL_CLASS_CONSTRUCTOR_PROPERTY_PARAMETER!>val y: String<!>)
@@ -1,21 +0,0 @@
external annotation class A(val x: Int)
val x: Int
external get() = definedExternally
class B
val B.x: Int
external get() = definedExternally
class C {
val a: Int
external get() = definedExternally
}
external class D {
val a: Int
external get() = definedExternally
}
external data class E(val x: Int)
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
external annotation class <!WRONG_EXTERNAL_DECLARATION!>A(val x: Int)<!>
val x: Int
@@ -14,7 +14,7 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.js.PredefinedAnnotation
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.name.JsStandardClassIds
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorUtils
@@ -28,7 +28,8 @@ import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils
object JsExternalChecker : DeclarationChecker {
val DEFINED_EXTERNALLY_PROPERTY_NAMES = setOf(FqNameUnsafe("kotlin.js.noImpl"), FqNameUnsafe("kotlin.js.definedExternally"))
val DEFINED_EXTERNALLY_PROPERTY_NAMES = JsStandardClassIds.Callables.definedExternallyPropertyNames
.map { it.asSingleFqName().toUnsafe() }
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
if (!AnnotationsUtils.isNativeObject(descriptor)) return
@@ -1,4 +1,5 @@
// IGNORE_BACKEND_K1: JS_IR
// IGNORE_BACKEND_K2: JS_IR
// IGNORE_BACKEND: JS_IR_ES6
// TODO: Unmute when extension functions are supported in external declarations.
// IGNORE_BACKEND: JS
@@ -1,4 +1,5 @@
// IGNORE_BACKEND_K1: JS_IR
// IGNORE_BACKEND_K2: JS_IR
// IGNORE_BACKEND: JS_IR_ES6
// TODO: Unmute when extension functions are supported in external declarations.
// IGNORE_BACKEND: JS