[FIR JS] Implement FirJsExportDeclarationChecker
This commit is contained in:
+22
@@ -4987,6 +4987,28 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirJsErrors.WRONG_EXPORTED_DECLARATION) { firDiagnostic ->
|
||||
WrongExportedDeclarationImpl(
|
||||
firDiagnostic.a,
|
||||
firDiagnostic as KtPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirJsErrors.NON_EXPORTABLE_TYPE) { firDiagnostic ->
|
||||
NonExportableTypeImpl(
|
||||
firDiagnostic.a,
|
||||
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.b),
|
||||
firDiagnostic as KtPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirJsErrors.NON_CONSUMABLE_EXPORTED_IDENTIFIER) { firDiagnostic ->
|
||||
NonConsumableExportedIdentifierImpl(
|
||||
firDiagnostic.a,
|
||||
firDiagnostic as KtPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirJsErrors.DELEGATION_BY_DYNAMIC) { firDiagnostic ->
|
||||
DelegationByDynamicImpl(
|
||||
firDiagnostic as KtPsiDiagnostic,
|
||||
|
||||
+16
@@ -3466,6 +3466,22 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
||||
override val diagnosticClass get() = NestedJsExport::class
|
||||
}
|
||||
|
||||
abstract class WrongExportedDeclaration : KtFirDiagnostic<KtElement>() {
|
||||
override val diagnosticClass get() = WrongExportedDeclaration::class
|
||||
abstract val kind: String
|
||||
}
|
||||
|
||||
abstract class NonExportableType : KtFirDiagnostic<KtElement>() {
|
||||
override val diagnosticClass get() = NonExportableType::class
|
||||
abstract val kind: String
|
||||
abstract val type: KtType
|
||||
}
|
||||
|
||||
abstract class NonConsumableExportedIdentifier : KtFirDiagnostic<KtElement>() {
|
||||
override val diagnosticClass get() = NonConsumableExportedIdentifier::class
|
||||
abstract val name: String
|
||||
}
|
||||
|
||||
abstract class DelegationByDynamic : KtFirDiagnostic<KtElement>() {
|
||||
override val diagnosticClass get() = DelegationByDynamic::class
|
||||
}
|
||||
|
||||
+19
@@ -4195,6 +4195,25 @@ internal class NestedJsExportImpl(
|
||||
override val token: KtLifetimeToken,
|
||||
) : KtFirDiagnostic.NestedJsExport(), KtAbstractFirDiagnostic<KtElement>
|
||||
|
||||
internal class WrongExportedDeclarationImpl(
|
||||
override val kind: String,
|
||||
override val firDiagnostic: KtPsiDiagnostic,
|
||||
override val token: KtLifetimeToken,
|
||||
) : KtFirDiagnostic.WrongExportedDeclaration(), KtAbstractFirDiagnostic<KtElement>
|
||||
|
||||
internal class NonExportableTypeImpl(
|
||||
override val kind: String,
|
||||
override val type: KtType,
|
||||
override val firDiagnostic: KtPsiDiagnostic,
|
||||
override val token: KtLifetimeToken,
|
||||
) : KtFirDiagnostic.NonExportableType(), KtAbstractFirDiagnostic<KtElement>
|
||||
|
||||
internal class NonConsumableExportedIdentifierImpl(
|
||||
override val name: String,
|
||||
override val firDiagnostic: KtPsiDiagnostic,
|
||||
override val token: KtLifetimeToken,
|
||||
) : KtFirDiagnostic.NonConsumableExportedIdentifier(), KtAbstractFirDiagnostic<KtElement>
|
||||
|
||||
internal class DelegationByDynamicImpl(
|
||||
override val firDiagnostic: KtPsiDiagnostic,
|
||||
override val token: KtLifetimeToken,
|
||||
|
||||
+10
@@ -98,6 +98,16 @@ object JS_DIAGNOSTICS_LIST : DiagnosticList("FirJsErrors") {
|
||||
|
||||
val EXPORT by object : DiagnosticGroup("Export") {
|
||||
val NESTED_JS_EXPORT by error<KtElement>()
|
||||
val WRONG_EXPORTED_DECLARATION by error<KtElement>(PositioningStrategy.DECLARATION_SIGNATURE_OR_DEFAULT) {
|
||||
parameter<String>("kind")
|
||||
}
|
||||
val NON_EXPORTABLE_TYPE by warning<KtElement>(PositioningStrategy.DECLARATION_SIGNATURE_OR_DEFAULT) {
|
||||
parameter<String>("kind")
|
||||
parameter<ConeKotlinType>("type")
|
||||
}
|
||||
val NON_CONSUMABLE_EXPORTED_IDENTIFIER by warning<KtElement>(PositioningStrategy.DEFAULT) {
|
||||
parameter<String>("name")
|
||||
}
|
||||
}
|
||||
|
||||
val DYNAMICS by object : DiagnosticGroup("Dynamics") {
|
||||
|
||||
@@ -7,6 +7,7 @@ plugins {
|
||||
|
||||
dependencies {
|
||||
api(project(":core:compiler.common.js"))
|
||||
api(project(":js:js.ast"))
|
||||
api(project(":compiler:fir:checkers"))
|
||||
|
||||
/*
|
||||
|
||||
+3
@@ -81,6 +81,9 @@ object FirJsErrors {
|
||||
|
||||
// Export
|
||||
val NESTED_JS_EXPORT by error0<KtElement>()
|
||||
val WRONG_EXPORTED_DECLARATION by error1<KtElement, String>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT)
|
||||
val NON_EXPORTABLE_TYPE by warning2<KtElement, String, ConeKotlinType>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT)
|
||||
val NON_CONSUMABLE_EXPORTED_IDENTIFIER by warning1<KtElement, String>()
|
||||
|
||||
// Dynamics
|
||||
val DELEGATION_BY_DYNAMIC by error0<KtElement>()
|
||||
|
||||
+15
@@ -46,6 +46,8 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.NESTED_CLASS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.NESTED_EXTERNAL_DECLARATION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.NESTED_JS_EXPORT
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.NON_ABSTRACT_MEMBER_OF_EXTERNAL_INTERFACE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.NON_CONSUMABLE_EXPORTED_IDENTIFIER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.NON_EXPORTABLE_TYPE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.NON_EXTERNAL_DECLARATION_IN_INAPPROPRIATE_FILE
|
||||
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
|
||||
@@ -54,6 +56,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.RUNTIME_ANNO
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.UNCHECKED_CAST_TO_EXTERNAL_INTERFACE
|
||||
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_EXPORTED_DECLARATION
|
||||
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
|
||||
@@ -169,6 +172,18 @@ object FirJsErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
|
||||
)
|
||||
map.put(EXTERNAL_INTERFACE_AS_CLASS_LITERAL, "Can't refer to external interface from class literal")
|
||||
map.put(NESTED_JS_EXPORT, "@JsExport is only allowed on files and top-level declarations")
|
||||
map.put(WRONG_EXPORTED_DECLARATION, "Declaration of such kind ({0}) can''t be exported to JS", CommonRenderers.STRING)
|
||||
map.put(
|
||||
NON_EXPORTABLE_TYPE,
|
||||
"Exported declaration uses non-exportable {0} type: {1}",
|
||||
CommonRenderers.STRING,
|
||||
FirDiagnosticRenderers.RENDER_TYPE,
|
||||
)
|
||||
map.put(
|
||||
NON_CONSUMABLE_EXPORTED_IDENTIFIER,
|
||||
"Exported declaration contains non-consumable identifier '${0}', that can't be represented inside TS definitions and ESM",
|
||||
CommonRenderers.STRING,
|
||||
)
|
||||
|
||||
map.checkMissingMessages(FirJsErrors)
|
||||
}
|
||||
|
||||
+40
-6
@@ -8,22 +8,22 @@
|
||||
package org.jetbrains.kotlin.fir.analysis.js.checkers
|
||||
|
||||
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.*
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.directOverriddenFunctions
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.getAnnotationStringParameter
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClassSymbol
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.hasAnnotationOrInsideAnnotatedClass
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.*
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isExpect
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isExternal
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isInterface
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.modality
|
||||
import org.jetbrains.kotlin.fir.isSubstitutionOrIntersectionOverride
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.js.PredefinedAnnotation
|
||||
import org.jetbrains.kotlin.js.common.isES5IdentifierPart
|
||||
import org.jetbrains.kotlin.js.common.isES5IdentifierStart
|
||||
import org.jetbrains.kotlin.name.JsStandardClassIds
|
||||
|
||||
private val FirBasedSymbol<*>.isExternal
|
||||
@@ -72,6 +72,13 @@ fun FirBasedSymbol<*>.getJsName(session: FirSession): String? {
|
||||
return getAnnotationStringParameter(JsStandardClassIds.Annotations.JsName, session)
|
||||
}
|
||||
|
||||
fun sanitizeName(name: String): String {
|
||||
if (name.isEmpty()) return "_"
|
||||
|
||||
val first = name.first().let { if (it.isES5IdentifierStart()) it else '_' }
|
||||
return first.toString() + name.drop(1).map { if (it.isES5IdentifierPart()) it else '_' }.joinToString("")
|
||||
}
|
||||
|
||||
fun FirBasedSymbol<*>.isNativeObject(session: FirSession): Boolean {
|
||||
if (hasAnnotationOrInsideAnnotatedClass(JsStandardClassIds.Annotations.JsNative, session) || isEffectivelyExternal(session)) {
|
||||
return true
|
||||
@@ -109,8 +116,35 @@ fun FirBasedSymbol<*>.isPredefinedObject(session: FirSession): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
fun FirBasedSymbol<*>.isExportedObject(session: FirSession): Boolean {
|
||||
val declaration = fir
|
||||
|
||||
if (declaration is FirMemberDeclaration) {
|
||||
val visibility = declaration.visibility
|
||||
if (visibility != Visibilities.Public && visibility != Visibilities.Protected) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return when {
|
||||
hasAnnotationOrInsideAnnotatedClass(JsStandardClassIds.Annotations.JsExportIgnore, session) -> false
|
||||
hasAnnotationOrInsideAnnotatedClass(JsStandardClassIds.Annotations.JsExport, session) -> true
|
||||
else -> getContainingFile(session)?.hasAnnotation(JsStandardClassIds.Annotations.JsExport, session) == true
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirBasedSymbol<*>.getContainingFile(session: FirSession): FirFile? {
|
||||
return when (this) {
|
||||
is FirCallableSymbol<*> -> session.firProvider.getFirCallableContainerFile(this)
|
||||
is FirClassLikeSymbol<*> -> session.firProvider.getFirClassifierContainerFileIfAny(this)
|
||||
else -> return null
|
||||
}
|
||||
}
|
||||
|
||||
fun FirBasedSymbol<*>.isNativeObject(context: CheckerContext) = isNativeObject(context.session)
|
||||
|
||||
fun FirBasedSymbol<*>.isNativeInterface(context: CheckerContext) = isNativeInterface(context.session)
|
||||
|
||||
fun FirBasedSymbol<*>.isPredefinedObject(context: CheckerContext) = isPredefinedObject(context.session)
|
||||
|
||||
fun FirBasedSymbol<*>.isExportedObject(context: CheckerContext) = isExportedObject(context.session)
|
||||
|
||||
+1
@@ -28,6 +28,7 @@ object JsDeclarationCheckers : DeclarationCheckers() {
|
||||
FirJsExternalFileChecker,
|
||||
FirJsNameChecker,
|
||||
FirJsExportAnnotationChecker,
|
||||
FirJsExportDeclarationChecker,
|
||||
)
|
||||
|
||||
override val classCheckers: Set<FirClassChecker>
|
||||
|
||||
+224
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
* 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.KtFakeSourceElementKind
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirBasicDeclarationChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.getAnnotationFirstArgument
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.isTopLevel
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.js.checkers.isEffectivelyExternal
|
||||
import org.jetbrains.kotlin.fir.analysis.js.checkers.isExportedObject
|
||||
import org.jetbrains.kotlin.fir.analysis.js.checkers.sanitizeName
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.*
|
||||
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
|
||||
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.js.common.RESERVED_KEYWORDS
|
||||
import org.jetbrains.kotlin.js.common.SPECIAL_KEYWORDS
|
||||
import org.jetbrains.kotlin.name.JsStandardClassIds
|
||||
|
||||
object FirJsExportDeclarationChecker : FirBasicDeclarationChecker() {
|
||||
override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
if (!declaration.symbol.isExportedObject(context) || declaration !is FirMemberDeclaration) {
|
||||
return
|
||||
}
|
||||
|
||||
fun checkTypeParameter(typeParameter: FirTypeParameterRef) {
|
||||
for (upperBound in typeParameter.symbol.resolvedBounds) {
|
||||
if (!upperBound.type.isExportable(context.session)) {
|
||||
reporter.reportOn(typeParameter.source, FirJsErrors.NON_EXPORTABLE_TYPE, "upper bound", upperBound.type, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun checkValueParameter(valueParameter: FirValueParameter) {
|
||||
val type = valueParameter.returnTypeRef.coneType
|
||||
if (!type.isExportable(context.session)) {
|
||||
reporter.reportOn(valueParameter.source, FirJsErrors.NON_EXPORTABLE_TYPE, "parameter", type, context)
|
||||
}
|
||||
}
|
||||
|
||||
val hasJsName = declaration.hasAnnotation(JsStandardClassIds.Annotations.JsName, context.session)
|
||||
|
||||
fun reportWrongExportedDeclaration(kind: String) {
|
||||
reporter.reportOn(declaration.source, FirJsErrors.WRONG_EXPORTED_DECLARATION, kind, context)
|
||||
}
|
||||
|
||||
if (declaration.isExpect) {
|
||||
reportWrongExportedDeclaration("expect")
|
||||
}
|
||||
|
||||
validateDeclarationOnConsumableName(declaration, context, reporter)
|
||||
|
||||
when (declaration) {
|
||||
is FirFunction -> {
|
||||
for (typeParameter in declaration.typeParameters) {
|
||||
checkTypeParameter(typeParameter)
|
||||
}
|
||||
|
||||
if (declaration.isInlineWithReified) {
|
||||
reportWrongExportedDeclaration("inline function with reified type parameters")
|
||||
return
|
||||
}
|
||||
|
||||
if (declaration.isSuspend) {
|
||||
reportWrongExportedDeclaration("suspend function")
|
||||
return
|
||||
}
|
||||
|
||||
if (declaration is FirConstructor && !declaration.isPrimary && !hasJsName) {
|
||||
reportWrongExportedDeclaration("secondary constructor without @JsName")
|
||||
}
|
||||
|
||||
// Properties are checked instead of property accessors
|
||||
if (declaration is FirPropertyAccessor) {
|
||||
return
|
||||
}
|
||||
|
||||
for (parameter in declaration.valueParameters) {
|
||||
checkValueParameter(parameter)
|
||||
}
|
||||
|
||||
val returnType = declaration.returnTypeRef.coneType
|
||||
|
||||
if (!returnType.isExportable(context.session)) {
|
||||
reporter.reportOn(declaration.source, FirJsErrors.NON_EXPORTABLE_TYPE, "return type", returnType, context)
|
||||
}
|
||||
}
|
||||
|
||||
is FirProperty -> {
|
||||
if (declaration.source?.kind == KtFakeSourceElementKind.PropertyFromParameter) {
|
||||
return
|
||||
}
|
||||
|
||||
if (declaration.isExtension) {
|
||||
reportWrongExportedDeclaration("extension property")
|
||||
return
|
||||
}
|
||||
|
||||
val returnType = declaration.returnTypeRef.coneType
|
||||
|
||||
if (!returnType.isExportable(context.session)) {
|
||||
reporter.reportOn(declaration.source, FirJsErrors.NON_EXPORTABLE_TYPE, "return type", returnType, context)
|
||||
}
|
||||
}
|
||||
|
||||
is FirClass -> {
|
||||
for (typeParameter in declaration.typeParameters) {
|
||||
checkTypeParameter(typeParameter)
|
||||
}
|
||||
|
||||
val wrongDeclaration: String? = when (declaration.classKind) {
|
||||
ClassKind.ANNOTATION_CLASS -> "annotation class"
|
||||
ClassKind.CLASS -> when {
|
||||
context.isInsideInterface -> "nested class inside exported interface"
|
||||
declaration.isInline -> "value class"
|
||||
else -> null
|
||||
}
|
||||
else -> if (context.isInsideInterface) {
|
||||
"${if (declaration.status.isCompanion) "companion object" else "nested/inner declaration"} inside exported interface"
|
||||
} else null
|
||||
}
|
||||
|
||||
if (wrongDeclaration != null) {
|
||||
reportWrongExportedDeclaration(wrongDeclaration)
|
||||
}
|
||||
}
|
||||
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
private val CheckerContext.isInsideInterface
|
||||
get(): Boolean {
|
||||
val parent = containingDeclarations.lastOrNull() as? FirClass
|
||||
return parent != null && parent.isInterface
|
||||
}
|
||||
|
||||
private val FirCallableDeclaration.isInlineWithReified: Boolean
|
||||
get() = when (this) {
|
||||
is FirPropertyAccessor -> {
|
||||
@OptIn(SymbolInternals::class)
|
||||
this.propertySymbol.fir.isInlineWithReified
|
||||
}
|
||||
else -> typeParameters.any { it.symbol.isReified }
|
||||
}
|
||||
|
||||
private fun ConeKotlinType.isExportableReturn(session: FirSession, currentlyProcessed: MutableSet<ConeKotlinType> = mutableSetOf()) =
|
||||
isUnit || isExportable(session, currentlyProcessed)
|
||||
|
||||
private fun ConeKotlinType.isExportable(
|
||||
session: FirSession,
|
||||
currentlyProcessed: MutableSet<ConeKotlinType> = mutableSetOf(),
|
||||
): Boolean {
|
||||
if (!currentlyProcessed.add(this)) {
|
||||
return true
|
||||
}
|
||||
|
||||
currentlyProcessed.add(this)
|
||||
val hasNonExportableArgument = typeArguments.any { it.type?.isExportable(session, currentlyProcessed) != true }
|
||||
|
||||
if (hasNonExportableArgument) {
|
||||
currentlyProcessed.remove(this)
|
||||
return false
|
||||
}
|
||||
|
||||
currentlyProcessed.remove(this)
|
||||
|
||||
if (isBasicFunctionType(session)) {
|
||||
typeArguments.lastOrNull()?.type?.isExportableReturn(session, currentlyProcessed)
|
||||
}
|
||||
|
||||
val nonNullable = withNullability(ConeNullability.NOT_NULL, session.typeContext)
|
||||
val isPrimitiveExportableType = nonNullable.isAny || nonNullable.isNullableAny
|
||||
|| nonNullable is ConeDynamicType || isPrimitiveExportableConeKotlinType
|
||||
val symbol = toSymbol(session)
|
||||
|
||||
return when {
|
||||
isPrimitiveExportableType -> true
|
||||
@OptIn(SymbolInternals::class)
|
||||
symbol?.fir is FirMemberDeclaration -> false
|
||||
isEnum -> true
|
||||
else -> symbol?.isEffectivelyExternal(session) == true || symbol?.isExportedObject(session) == true
|
||||
}
|
||||
}
|
||||
|
||||
private val ConeKotlinType.isPrimitiveExportableConeKotlinType: Boolean
|
||||
get() = this is ConeTypeParameterType
|
||||
|| isBoolean
|
||||
|| isThrowableOrNullableThrowable
|
||||
|| isString
|
||||
|| isPrimitiveNumberOrNullableType && !isLong
|
||||
|| isNothingOrNullableNothing
|
||||
|| isArrayType
|
||||
|
||||
private fun validateDeclarationOnConsumableName(
|
||||
declaration: FirMemberDeclaration,
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter,
|
||||
) {
|
||||
if (!context.isTopLevel || declaration.nameOrSpecialName.isSpecial) {
|
||||
return
|
||||
}
|
||||
|
||||
val jsNameArgument = declaration.symbol.getAnnotationFirstArgument(JsStandardClassIds.Annotations.JsName, context.session)
|
||||
val reportTarget = jsNameArgument?.source ?: declaration.source
|
||||
val name = (jsNameArgument as? FirConstExpression<*>)?.value as? String ?: declaration.nameOrSpecialName.asString()
|
||||
|
||||
if (name in SPECIAL_KEYWORDS || (name !in RESERVED_KEYWORDS && sanitizeName(name) == name)) {
|
||||
return
|
||||
}
|
||||
|
||||
reporter.reportOn(reportTarget, FirJsErrors.NON_CONSUMABLE_EXPORTED_IDENTIFIER, name, context)
|
||||
}
|
||||
}
|
||||
@@ -736,9 +736,13 @@ fun FirBasedSymbol<*>.hasAnnotationOrInsideAnnotatedClass(classId: ClassId, sess
|
||||
fun FirDeclaration.hasAnnotationOrInsideAnnotatedClass(classId: ClassId, session: FirSession) =
|
||||
symbol.hasAnnotationOrInsideAnnotatedClass(classId, session)
|
||||
|
||||
fun FirBasedSymbol<*>.getAnnotationStringParameter(classId: ClassId, session: FirSession): String? {
|
||||
fun FirBasedSymbol<*>.getAnnotationFirstArgument(classId: ClassId, session: FirSession): FirExpression? {
|
||||
val annotation = getAnnotationByClassId(classId, session) as? FirAnnotationCall
|
||||
val expression = annotation?.argumentMapping?.mapping?.values?.firstOrNull() as? FirConstExpression<*>
|
||||
return annotation?.argumentMapping?.mapping?.values?.firstOrNull()
|
||||
}
|
||||
|
||||
fun FirBasedSymbol<*>.getAnnotationStringParameter(classId: ClassId, session: FirSession): String? {
|
||||
val expression = getAnnotationFirstArgument(classId, session) as? FirConstExpression<*>
|
||||
return expression?.value as? String
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,10 @@ val ConeKotlinType.isBoolean: Boolean get() = isBuiltinType(StandardClassIds.Boo
|
||||
val ConeKotlinType.isNullableBoolean: Boolean get() = isBuiltinType(StandardClassIds.Boolean, true)
|
||||
val ConeKotlinType.isBooleanOrNullableBoolean: Boolean get() = isBuiltinType(StandardClassIds.Boolean, null)
|
||||
|
||||
val ConeKotlinType.isThrowableOrNullableThrowable: Boolean get() = isAnyOfBuiltinType(setOf(StandardClassIds.Throwable))
|
||||
|
||||
val ConeKotlinType.isChar: Boolean get() = isBuiltinType(StandardClassIds.Char, false)
|
||||
val ConeKotlinType.isCharOrNullableChar: Boolean get() = isAnyOfBuiltinType(setOf(StandardClassIds.Char))
|
||||
val ConeKotlinType.isString: Boolean get() = isBuiltinType(StandardClassIds.String, false)
|
||||
|
||||
val ConeKotlinType.isEnum: Boolean get() = isBuiltinType(StandardClassIds.Enum, false)
|
||||
@@ -37,6 +40,8 @@ val ConeKotlinType.isUInt: Boolean get() = isBuiltinType(StandardClassIds.UInt,
|
||||
val ConeKotlinType.isULong: Boolean get() = isBuiltinType(StandardClassIds.ULong, false)
|
||||
val ConeKotlinType.isPrimitiveOrNullablePrimitive: Boolean get() = isAnyOfBuiltinType(StandardClassIds.primitiveTypes)
|
||||
val ConeKotlinType.isPrimitive: Boolean get() = isPrimitiveOrNullablePrimitive && nullability == ConeNullability.NOT_NULL
|
||||
val ConeKotlinType.isPrimitiveNumberOrNullableType: Boolean
|
||||
get() = isPrimitiveOrNullablePrimitive && !isBooleanOrNullableBoolean && !isCharOrNullableChar
|
||||
val ConeKotlinType.isArrayType: Boolean
|
||||
get() {
|
||||
return isBuiltinType(StandardClassIds.Array, false) ||
|
||||
|
||||
@@ -540,15 +540,6 @@ fun FirBasedSymbol<*>.getOwnerLookupTag(): ConeClassLikeLookupTag? {
|
||||
}
|
||||
}
|
||||
|
||||
fun FirClassLikeSymbol<*>.getContainingClassLookupTag(): ConeClassLikeLookupTag? {
|
||||
return if (classId.isLocal) {
|
||||
(fir as? FirRegularClass)?.containingClassForLocal()
|
||||
} else {
|
||||
val ownerId = classId.outerClassId
|
||||
ownerId?.let { it.toLookupTag() }
|
||||
}
|
||||
}
|
||||
|
||||
fun FirBasedSymbol<*>.isVariableOrNamedFunction(): Boolean {
|
||||
return this is FirVariableSymbol || this is FirNamedFunctionSymbol || this is FirPropertyAccessorSymbol
|
||||
}
|
||||
|
||||
+4
-1
@@ -233,7 +233,10 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
|
||||
fun constructorTypeParametersFromConstructedClass(ownerTypeParameters: List<FirTypeParameterRef>): List<FirTypeParameterRef> {
|
||||
return ownerTypeParameters.mapNotNull {
|
||||
val declaredTypeParameter = (it as? FirTypeParameter) ?: return@mapNotNull null
|
||||
buildConstructedClassTypeParameterRef { symbol = declaredTypeParameter.symbol }
|
||||
buildConstructedClassTypeParameterRef {
|
||||
source = declaredTypeParameter.symbol.source?.fakeElement(KtFakeSourceElementKind.ConstructorTypeParameter)
|
||||
symbol = declaredTypeParameter.symbol
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.fir.PrivateForInline
|
||||
import org.jetbrains.kotlin.fir.declarations.FirTypeParameterRef
|
||||
import org.jetbrains.kotlin.fir.declarations.builder.buildOuterClassTypeParameterRef
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirFileSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
@@ -48,6 +49,7 @@ class Context<T> {
|
||||
var forcedElementSourceKind: KtSourceElementKind? = null
|
||||
val dispatchReceiverTypesStack = mutableListOf<ConeClassLikeType>()
|
||||
var containerIsExpect: Boolean = false
|
||||
var containingFileSymbol: FirFileSymbol? = null
|
||||
|
||||
fun pushFirTypeParameters(isInnerOrLocal: Boolean, parameters: List<FirTypeParameterRef>) {
|
||||
capturedTypeParameters.add(StatusFirTypeParameterSymbolList(isInnerOrLocal, parameters.map { it.symbol }))
|
||||
|
||||
@@ -10,9 +10,11 @@ import org.jetbrains.kotlin.fir.declarations.utils.isLocal
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isSynthetic
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
||||
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
||||
import org.jetbrains.kotlin.fir.types.ConeIntersectionType
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.toLookupTag
|
||||
|
||||
fun FirCallableSymbol<*>.dispatchReceiverClassTypeOrNull(): ConeClassLikeType? =
|
||||
fir.dispatchReceiverClassTypeOrNull()
|
||||
@@ -41,6 +43,15 @@ fun FirRegularClass.containingClassForLocal(): ConeClassLikeLookupTag? =
|
||||
fun FirDanglingModifierList.containingClass(): ConeClassLikeLookupTag? =
|
||||
containingClassAttr
|
||||
|
||||
fun FirClassLikeSymbol<*>.getContainingClassLookupTag(): ConeClassLikeLookupTag? {
|
||||
return if (classId.isLocal) {
|
||||
(fir as? FirRegularClass)?.containingClassForLocal()
|
||||
} else {
|
||||
val ownerId = classId.outerClassId
|
||||
ownerId?.toLookupTag()
|
||||
}
|
||||
}
|
||||
|
||||
private object ContainingClassKey : FirDeclarationDataKey()
|
||||
var FirCallableDeclaration.containingClassForStaticMemberAttr: ConeClassLikeLookupTag? by FirDeclarationDataRegistry.data(ContainingClassKey)
|
||||
var FirRegularClass.containingClassForLocalAttr: ConeClassLikeLookupTag? by FirDeclarationDataRegistry.data(ContainingClassKey)
|
||||
|
||||
+2
-12
@@ -7,9 +7,9 @@ package org.jetbrains.kotlin.fir.declarations.comparators
|
||||
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.classId
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.nameOrSpecialName
|
||||
import org.jetbrains.kotlin.fir.render
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRefComparator
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
object FirMemberDeclarationComparator : Comparator<FirMemberDeclaration> {
|
||||
// Comparing different kinds of callable members by assigning distinct priorities to those members.
|
||||
@@ -28,16 +28,6 @@ object FirMemberDeclarationComparator : Comparator<FirMemberDeclaration> {
|
||||
is FirBackingField -> 0
|
||||
}
|
||||
|
||||
private val FirMemberDeclaration.name: Name
|
||||
get() = when (this) {
|
||||
is FirCallableDeclaration ->
|
||||
this.symbol.callableId.callableName
|
||||
is FirClass ->
|
||||
this.classId.shortClassName
|
||||
is FirTypeAlias ->
|
||||
this.name
|
||||
}
|
||||
|
||||
override fun compare(a: FirMemberDeclaration, b: FirMemberDeclaration): Int {
|
||||
val priorityDiff = a.priority - b.priority
|
||||
if (priorityDiff != 0) {
|
||||
@@ -51,7 +41,7 @@ object FirMemberDeclarationComparator : Comparator<FirMemberDeclaration> {
|
||||
return 0
|
||||
}
|
||||
|
||||
return a.name.compareTo(b.name)
|
||||
return a.nameOrSpecialName.compareTo(b.nameOrSpecialName)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+11
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
||||
import org.jetbrains.kotlin.fir.types.coneTypeSafe
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
val FirTypeAlias.expandedConeType: ConeClassLikeType? get() = expandedTypeRef.coneTypeSafe()
|
||||
|
||||
@@ -45,3 +46,13 @@ val FirDeclaration.isNonLocal
|
||||
}
|
||||
|
||||
val FirCallableDeclaration.isExtension get() = receiverParameter != null
|
||||
|
||||
val FirMemberDeclaration.nameOrSpecialName: Name
|
||||
get() = when (this) {
|
||||
is FirCallableDeclaration ->
|
||||
this.symbol.callableId.callableName
|
||||
is FirClass ->
|
||||
this.classId.shortClassName
|
||||
is FirTypeAlias ->
|
||||
this.name
|
||||
}
|
||||
|
||||
@@ -58,6 +58,10 @@ sealed class KtFakeSourceElementKind(final override val shouldSkipErrorTypeRepor
|
||||
// with a fake source which refers to containing class
|
||||
object ImplicitConstructor : KtFakeSourceElementKind()
|
||||
|
||||
// for constructor type parameters, because they refer to the same source
|
||||
// as the class type parameters themselves
|
||||
object ConstructorTypeParameter : KtFakeSourceElementKind()
|
||||
|
||||
// for constructors which do not have delegated constructor call the fake one is generated
|
||||
// with a fake sources which refers to the original constructor
|
||||
object DelegatingConstructorCall : KtFakeSourceElementKind()
|
||||
|
||||
+4
-4
@@ -3,7 +3,7 @@
|
||||
|
||||
fun f1(x: String) {}
|
||||
fun f2(f: () -> Unit) {}
|
||||
fun test1() = <!INAPPLICABLE_CANDIDATE!>f2<!>(::<!UNRESOLVED_REFERENCE!>f1<!>)
|
||||
fun test1() = <!INAPPLICABLE_CANDIDATE("fun f2(f: () -> Unit): Unit")!>f2<!>(::<!UNRESOLVED_REFERENCE("f1")!>f1<!>)
|
||||
|
||||
|
||||
@Target(AnnotationTarget.TYPE_PARAMETER, AnnotationTarget.TYPE)
|
||||
@@ -12,14 +12,14 @@ annotation class Ann
|
||||
fun <@Ann R : @Ann Any> f3(a: Array<@Ann R>): Array<@Ann R?> = null!!
|
||||
|
||||
fun test2(a: @Ann Array<in @Ann Int>) {
|
||||
val r: Array<in Int?> = f3(<!ARGUMENT_TYPE_MISMATCH!>a<!>)
|
||||
val r: Array<in Int?> = f3(<!ARGUMENT_TYPE_MISMATCH("kotlin/Array<@R|Ann|() R>; @R|Ann|() kotlin/Array<in @R|Ann|() kotlin/Int>")!>a<!>)
|
||||
}
|
||||
|
||||
|
||||
var test3: Int = 0
|
||||
set(s: <!WRONG_SETTER_PARAMETER_TYPE!>@Ann String<!>) {}
|
||||
set(s: <!WRONG_SETTER_PARAMETER_TYPE("kotlin/Int; @R|Ann|() kotlin/String")!>@Ann String<!>) {}
|
||||
|
||||
|
||||
fun f4(fn: (@Ann Int, @Ann Int) -> Unit) {}
|
||||
|
||||
val test4 = f4 <!ARGUMENT_TYPE_MISMATCH!>{ single -> }<!>
|
||||
val test4 = f4 <!ARGUMENT_TYPE_MISMATCH("kotlin/Function2<@R|Ann|() kotlin/Int, @R|Ann|() kotlin/Int, kotlin/Unit>; kotlin/Function1<@R|Ann|() kotlin/Int, kotlin/Unit>")!>{ single -> }<!>
|
||||
|
||||
Vendored
+1
-1
@@ -11,5 +11,5 @@ open class B1 {
|
||||
}
|
||||
|
||||
class D1 : B1() {
|
||||
<!NOTHING_TO_OVERRIDE!>override<!> fun foo() {}
|
||||
<!NOTHING_TO_OVERRIDE("foo")!>override<!> fun foo() {}
|
||||
}
|
||||
|
||||
+1
-1
@@ -11,5 +11,5 @@ class C<T> {
|
||||
}
|
||||
|
||||
fun test(a: C<out CharSequence>) {
|
||||
a[1] = <!ARGUMENT_TYPE_MISMATCH!>25<!>
|
||||
a[1] = <!ARGUMENT_TYPE_MISMATCH("@R|A|() CapturedType(out kotlin/CharSequence); kotlin/Int")!>25<!>
|
||||
}
|
||||
|
||||
+5
-5
@@ -15,7 +15,7 @@ interface B {
|
||||
fun <T> a(@An arg: @An Int)
|
||||
}
|
||||
|
||||
<!CONFLICTING_INHERITED_MEMBERS!>interface C<!> : A, B
|
||||
<!CONFLICTING_INHERITED_MEMBERS("C; a, a")!>interface C<!> : A, B
|
||||
|
||||
@An
|
||||
abstract class D {
|
||||
@@ -23,8 +23,8 @@ abstract class D {
|
||||
abstract val d: @An Int
|
||||
}
|
||||
|
||||
<!ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED!>class E<!> : D(), A
|
||||
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class F<!> : A
|
||||
<!ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED("Class E; d")!>class E<!> : D(), A
|
||||
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED("Class F; a")!>class F<!> : A
|
||||
|
||||
@An
|
||||
interface G {
|
||||
@@ -44,5 +44,5 @@ interface GI : G {
|
||||
override fun a(@An arg: @An Int) {}
|
||||
}
|
||||
|
||||
<!MANY_IMPL_MEMBER_NOT_IMPLEMENTED!>class AG1<!>(val a: A, val g: G) : A by a, G by g
|
||||
<!MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED!>class AG2<!>() : AI, GI
|
||||
<!MANY_IMPL_MEMBER_NOT_IMPLEMENTED("Class AG1; a")!>class AG1<!>(val a: A, val g: G) : A by a, G by g
|
||||
<!MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED("Class AG2; a")!>class AG2<!>() : AI, GI
|
||||
|
||||
+1
-1
@@ -7,5 +7,5 @@ annotation class Ann(val s: String = "")
|
||||
fun foo() {}
|
||||
|
||||
val bar = foo(
|
||||
<!TOO_MANY_ARGUMENTS!>15<!>
|
||||
<!TOO_MANY_ARGUMENTS("public final fun /foo(): R|kotlin/Unit|")!>15<!>
|
||||
)
|
||||
|
||||
Vendored
+1
-1
@@ -13,5 +13,5 @@ class C<T> {
|
||||
class Out<out F>
|
||||
|
||||
fun test(a: C<out CharSequence>, y: Out<CharSequence>) {
|
||||
a + <!ARGUMENT_TYPE_MISMATCH!>y<!>
|
||||
a + <!ARGUMENT_TYPE_MISMATCH("Out<@R|A|() CapturedType(out kotlin/CharSequence)>; Out<kotlin/CharSequence>")!>y<!>
|
||||
}
|
||||
|
||||
+4
-4
@@ -15,12 +15,12 @@ interface A {
|
||||
|
||||
@An
|
||||
interface B : A {
|
||||
override val p1: <!PROPERTY_TYPE_MISMATCH_ON_OVERRIDE!>Int<!>
|
||||
override val p1: <!PROPERTY_TYPE_MISMATCH_ON_OVERRIDE("p1; @An() val p1: @R|An|() String")!>Int<!>
|
||||
@An
|
||||
override <!VAR_OVERRIDDEN_BY_VAL!>val<!> p2: @An String
|
||||
override fun test(arg: String): <!RETURN_TYPE_MISMATCH_ON_OVERRIDE!>Int<!>
|
||||
override <!VAR_OVERRIDDEN_BY_VAL("public abstract override val /B.p2: R|@R|An|() kotlin/String| public get(): R|@R|An|() kotlin/String|; public abstract var /A.p2: R|@R|An|() kotlin/String| public get(): R|@R|An|() kotlin/String| public set(value: R|@R|An|() kotlin/String|): R|kotlin/Unit|")!>val<!> p2: @An String
|
||||
override fun test(arg: String): <!RETURN_TYPE_MISMATCH_ON_OVERRIDE("test; @An() fun test(@An() arg: @R|An|() String): @R|An|() String")!>Int<!>
|
||||
}
|
||||
|
||||
interface C : A {
|
||||
override var p2: <!VAR_TYPE_MISMATCH_ON_OVERRIDE!>Int<!>
|
||||
override var p2: <!VAR_TYPE_MISMATCH_ON_OVERRIDE("p2; @An() var p2: @R|An|() String")!>Int<!>
|
||||
}
|
||||
|
||||
Vendored
+2
-2
@@ -27,7 +27,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
annotation class An
|
||||
|
||||
class B : A {
|
||||
override fun foo(): <!RETURN_TYPE_MISMATCH_ON_OVERRIDE!>String?<!> = null
|
||||
override fun foo(): <!RETURN_TYPE_MISMATCH_ON_OVERRIDE("foo; @NotNull() @An() @MyTypeQualifier() fun foo(): @EnhancedNullability String")!>String?<!> = null
|
||||
}
|
||||
|
||||
@An
|
||||
@@ -38,5 +38,5 @@ public interface C {
|
||||
}
|
||||
|
||||
class D : C {
|
||||
override fun foo(): <!RETURN_TYPE_MISMATCH_ON_OVERRIDE!>String?<!> = null
|
||||
override fun foo(): <!RETURN_TYPE_MISMATCH_ON_OVERRIDE("foo; @NotNull() @An() fun foo(): String")!>String?<!> = null
|
||||
}
|
||||
|
||||
Vendored
-15
@@ -1,15 +0,0 @@
|
||||
// !OPT_IN: kotlin.js.ExperimentalJsExport
|
||||
// !RENDER_DIAGNOSTICS_MESSAGES
|
||||
|
||||
package foo
|
||||
|
||||
@JsExport
|
||||
class C(val x: String) {
|
||||
constructor(x: Int): this(x.toString())
|
||||
}
|
||||
|
||||
@JsExport
|
||||
class C2(val x: String) {
|
||||
@JsName("JsNameProvided")
|
||||
constructor(x: Int): this(x.toString())
|
||||
}
|
||||
Vendored
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// !OPT_IN: kotlin.js.ExperimentalJsExport
|
||||
// !RENDER_DIAGNOSTICS_MESSAGES
|
||||
|
||||
|
||||
-14
@@ -1,14 +0,0 @@
|
||||
// !OPT_IN: kotlin.js.ExperimentalJsExport
|
||||
// !RENDER_DIAGNOSTICS_MESSAGES
|
||||
@file:JsExport
|
||||
|
||||
package foo
|
||||
|
||||
class C(val x: String) {
|
||||
constructor(x: Int): this(x.toString())
|
||||
}
|
||||
|
||||
class C2(val x: String) {
|
||||
@JsName("JsNameProvided")
|
||||
constructor(x: Int): this(x.toString())
|
||||
}
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// !OPT_IN: kotlin.js.ExperimentalJsExport
|
||||
// !RENDER_DIAGNOSTICS_MESSAGES
|
||||
@file:JsExport
|
||||
|
||||
+13
-13
@@ -4,18 +4,18 @@
|
||||
|
||||
package foo
|
||||
|
||||
@JsExport
|
||||
inline fun <reified T> inlineReifiedFun(x: Any) = x is T
|
||||
<!WRONG_EXPORTED_DECLARATION("inline function with reified type parameters")!>@JsExport
|
||||
inline fun <reified T> inlineReifiedFun(x: Any)<!> = x is T
|
||||
|
||||
@JsExport
|
||||
suspend fun suspendFun() { }
|
||||
<!WRONG_EXPORTED_DECLARATION("suspend function")!>@JsExport
|
||||
suspend fun suspendFun()<!> { }
|
||||
|
||||
@JsExport
|
||||
val String.extensionProperty
|
||||
<!WRONG_EXPORTED_DECLARATION("extension property")!>@JsExport
|
||||
val String.extensionProperty<!>
|
||||
get() = this.length
|
||||
|
||||
@JsExport
|
||||
annotation class AnnotationClass
|
||||
annotation class <!WRONG_EXPORTED_DECLARATION("annotation class")!>AnnotationClass<!>
|
||||
|
||||
@JsExport
|
||||
interface SomeInterface
|
||||
@@ -25,24 +25,24 @@ external interface GoodInterface
|
||||
|
||||
@JsExport
|
||||
interface InterfaceWithCompanion {
|
||||
companion object {
|
||||
companion <!WRONG_EXPORTED_DECLARATION("companion object inside exported interface")!>object<!> {
|
||||
fun foo() = 42
|
||||
}
|
||||
}
|
||||
|
||||
@JsExport
|
||||
interface OuterInterface {
|
||||
class Nested
|
||||
class <!WRONG_EXPORTED_DECLARATION("nested class inside exported interface")!>Nested<!>
|
||||
}
|
||||
|
||||
@JsExport
|
||||
value class A(val a: Int)
|
||||
value class <!WRONG_EXPORTED_DECLARATION("value class")!>A(val a: Int)<!>
|
||||
|
||||
@JsExport
|
||||
inline class B(val b: Int)
|
||||
inline class <!WRONG_EXPORTED_DECLARATION("value class")!>B(val b: Int)<!>
|
||||
|
||||
@JsExport
|
||||
inline value class C(val c: Int)
|
||||
inline value class <!WRONG_EXPORTED_DECLARATION("value class")!>C(val c: Int)<!>
|
||||
|
||||
@JsExport
|
||||
value inline class D(val d: Int)
|
||||
value inline class <!WRONG_EXPORTED_DECLARATION("value class")!>D(val d: Int)<!>
|
||||
|
||||
compiler/testData/diagnostics/testsWithJsStdLib/export/wrongExportedDeclarationInExportedFile.fir.kt
Vendored
-15
@@ -1,15 +0,0 @@
|
||||
// !OPT_IN: kotlin.js.ExperimentalJsExport
|
||||
// !RENDER_DIAGNOSTICS_MESSAGES
|
||||
|
||||
@file:JsExport
|
||||
|
||||
package foo
|
||||
|
||||
inline fun <reified T> inlineReifiedFun(x: Any) = x is T
|
||||
|
||||
suspend fun suspendFun() { }
|
||||
|
||||
val String.extensionProperty
|
||||
get() = this.length
|
||||
|
||||
annotation class AnnotationClass
|
||||
Vendored
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// !OPT_IN: kotlin.js.ExperimentalJsExport
|
||||
// !RENDER_DIAGNOSTICS_MESSAGES
|
||||
|
||||
|
||||
+4
@@ -43,6 +43,10 @@ object FirDiagnosticsDirectives : SimpleDirectivesContainer() {
|
||||
description = "Defines which parser should be used for FIR compiler"
|
||||
)
|
||||
|
||||
val RENDER_DIAGNOSTICS_MESSAGES by directive(
|
||||
description = "Forces diagnostic arguments to be rendered"
|
||||
)
|
||||
|
||||
val FIR_DISABLE_LAZY_RESOLVE_CHECKS by directive(
|
||||
description = "Temporary disables lazy resolve checks until the lazy resolve contract violation is fixed"
|
||||
)
|
||||
|
||||
+14
-7
@@ -70,6 +70,7 @@ class FirDiagnosticsHandler(testServices: TestServices) : FirAnalysisHandler(tes
|
||||
|
||||
val lightTreeComparingModeEnabled = FirDiagnosticsDirectives.COMPARE_WITH_LIGHT_TREE in currentModule.directives
|
||||
val lightTreeEnabled = currentModule.directives.singleValue(FirDiagnosticsDirectives.FIR_PARSER) == FirParser.LightTree
|
||||
val forceRenderArguments = FirDiagnosticsDirectives.RENDER_DIAGNOSTICS_MESSAGES in currentModule.directives
|
||||
|
||||
for (file in currentModule.files) {
|
||||
val firFile = info.mainFirFiles[file] ?: continue
|
||||
@@ -84,10 +85,11 @@ class FirDiagnosticsHandler(testServices: TestServices) : FirAnalysisHandler(tes
|
||||
diagnostics.diagnosticCodeMetaInfos(
|
||||
currentModule, file,
|
||||
diagnosticsService, globalMetadataInfoHandler,
|
||||
lightTreeEnabled, lightTreeComparingModeEnabled
|
||||
lightTreeEnabled, lightTreeComparingModeEnabled,
|
||||
forceRenderArguments,
|
||||
)
|
||||
globalMetadataInfoHandler.addMetadataInfosForFile(file, diagnosticsMetadataInfos)
|
||||
collectSyntaxDiagnostics(currentModule, file, firFile, lightTreeEnabled, lightTreeComparingModeEnabled)
|
||||
collectSyntaxDiagnostics(currentModule, file, firFile, lightTreeEnabled, lightTreeComparingModeEnabled, forceRenderArguments)
|
||||
collectDebugInfoDiagnostics(currentModule, file, firFile, lightTreeEnabled, lightTreeComparingModeEnabled)
|
||||
}
|
||||
}
|
||||
@@ -99,7 +101,8 @@ class FirDiagnosticsHandler(testServices: TestServices) : FirAnalysisHandler(tes
|
||||
testFile: TestFile,
|
||||
firFile: FirFile,
|
||||
lightTreeEnabled: Boolean,
|
||||
lightTreeComparingModeEnabled: Boolean
|
||||
lightTreeComparingModeEnabled: Boolean,
|
||||
forceRenderArguments: Boolean,
|
||||
) {
|
||||
val metaInfos = if (firFile.psi != null) {
|
||||
AnalyzingUtils.getSyntaxErrorRanges(firFile.psi!!).flatMap {
|
||||
@@ -109,7 +112,8 @@ class FirDiagnosticsHandler(testServices: TestServices) : FirAnalysisHandler(tes
|
||||
testFile,
|
||||
globalMetadataInfoHandler1 = globalMetadataInfoHandler,
|
||||
lightTreeEnabled,
|
||||
lightTreeComparingModeEnabled
|
||||
lightTreeComparingModeEnabled,
|
||||
forceRenderArguments,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
@@ -120,7 +124,8 @@ class FirDiagnosticsHandler(testServices: TestServices) : FirAnalysisHandler(tes
|
||||
testFile,
|
||||
globalMetadataInfoHandler1 = globalMetadataInfoHandler,
|
||||
lightTreeEnabled,
|
||||
lightTreeComparingModeEnabled
|
||||
lightTreeComparingModeEnabled,
|
||||
forceRenderArguments,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -323,7 +328,8 @@ fun List<KtDiagnostic>.diagnosticCodeMetaInfos(
|
||||
diagnosticsService: DiagnosticsService,
|
||||
globalMetadataInfoHandler: GlobalMetadataInfoHandler,
|
||||
lightTreeEnabled: Boolean,
|
||||
lightTreeComparingModeEnabled: Boolean
|
||||
lightTreeComparingModeEnabled: Boolean,
|
||||
forceRenderArguments: Boolean = false,
|
||||
): List<FirDiagnosticCodeMetaInfo> = flatMap { diagnostic ->
|
||||
if (!diagnosticsService.shouldRenderDiagnostic(
|
||||
module,
|
||||
@@ -339,7 +345,8 @@ fun List<KtDiagnostic>.diagnosticCodeMetaInfos(
|
||||
file,
|
||||
globalMetadataInfoHandler,
|
||||
lightTreeEnabled,
|
||||
lightTreeComparingModeEnabled
|
||||
lightTreeComparingModeEnabled,
|
||||
forceRenderArguments,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ object JsStandardClassIds {
|
||||
val JsExport = "JsExport".jsId()
|
||||
|
||||
@JvmField
|
||||
val JsExportIgnore = ClassId(JsExport.asSingleFqName(), Name.identifier("Ignore"))
|
||||
val JsExportIgnore = JsExport.createNestedClassId(Name.identifier("Ignore"))
|
||||
|
||||
@JvmField
|
||||
val annotationsRequiringExternal = setOf(JsModule, JsQualifier)
|
||||
|
||||
@@ -40,7 +40,6 @@ interface TypeSystemCommonBackendContext : TypeSystemContext {
|
||||
|
||||
fun KotlinTypeMarker.makeNullable(): KotlinTypeMarker =
|
||||
asSimpleType()?.withNullability(true) ?: this
|
||||
|
||||
fun TypeConstructorMarker.getPrimitiveType(): PrimitiveType?
|
||||
fun TypeConstructorMarker.getPrimitiveArrayType(): PrimitiveType?
|
||||
|
||||
|
||||
Reference in New Issue
Block a user