diff --git a/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/FirJsHelpers.kt b/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/FirJsHelpers.kt index 6d6f142072a..7d6c6a0700b 100644 --- a/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/FirJsHelpers.kt +++ b/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/FirJsHelpers.kt @@ -10,12 +10,12 @@ package org.jetbrains.kotlin.fir.analysis.js.checkers import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibilities -import org.jetbrains.kotlin.descriptors.effectiveVisibility 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.declarations.* import org.jetbrains.kotlin.fir.declarations.utils.* +import org.jetbrains.kotlin.fir.declarations.utils.isActual import org.jetbrains.kotlin.fir.declarations.utils.isExpect import org.jetbrains.kotlin.fir.declarations.utils.isExternal import org.jetbrains.kotlin.fir.isSubstitutionOrIntersectionOverride @@ -101,13 +101,26 @@ fun FirBasedSymbol<*>.isNativeInterface(session: FirSession): Boolean { return isNativeObject(session) && (fir as? FirClass)?.isInterface == true } -private val FirBasedSymbol<*>.isExpect +fun FirBasedSymbol<*>.isLibraryObject(session: FirSession): Boolean { + return hasAnnotationOrInsideAnnotatedClass(JsStandardClassIds.Annotations.JsLibrary, session) +} + +fun FirBasedSymbol<*>.isPresentInGeneratedCode(session: FirSession) = !isNativeObject(session) && !isLibraryObject(session) + +internal val FirBasedSymbol<*>.isExpect get() = when (this) { is FirCallableSymbol<*> -> isExpect is FirClassSymbol<*> -> isExpect else -> false } +internal val FirBasedSymbol<*>.isActual + get() = when (this) { + is FirCallableSymbol<*> -> isActual + is FirClassSymbol<*> -> isActual + else -> false + } + fun FirBasedSymbol<*>.isPredefinedObject(session: FirSession): Boolean { if (fir is FirMemberDeclaration && isExpect) return true if (isEffectivelyExternalMember(session)) return true @@ -154,6 +167,8 @@ fun FirBasedSymbol<*>.isPredefinedObject(context: CheckerContext) = isPredefined fun FirBasedSymbol<*>.isExportedObject(context: CheckerContext) = isExportedObject(context.session) +fun FirBasedSymbol<*>.isLibraryObject(context: CheckerContext) = isLibraryObject(context.session) + internal fun FirClass.superClassNotAny(session: FirSession) = superConeTypes .filterNot { it.isAny || it.isNullableAny } .find { it.toSymbol(session)?.classKind == ClassKind.CLASS } @@ -161,39 +176,3 @@ internal fun FirClass.superClassNotAny(session: FirSession) = superConeTypes internal fun getRootClassLikeSymbolOrSelf(symbol: FirBasedSymbol<*>, session: FirSession): FirBasedSymbol<*> { return symbol.getContainingClassSymbol(session)?.let { getRootClassLikeSymbolOrSelf(it, session) } ?: symbol } - -internal fun FirBasedSymbol<*>.getStableNameInJavaScript(session: FirSession): String? { - val jsName = getJsName(session) - if (jsName != null) { - return jsName - } - val hasStableNameInJavaScript = when { - isEffectivelyExternal(session) -> true - isExportedObject(session) -> true - else -> false - } - - // TODO: rethink in KT-60554 - val hasPublicName = when (this) { - is FirClassLikeSymbol -> !isLocal - is FirCallableSymbol -> { - val parentClass = getContainingClassSymbol(session) - if (parentClass != null) { - when (visibility) { - is Visibilities.Public -> true - is Visibilities.Protected -> !parentClass.isFinal && parentClass.visibility.isPublicAPI - else -> false - } - } else { - !callableId.isLocal && effectiveVisibility.publicApi - } - } - else -> false - } - - if (hasStableNameInJavaScript || hasPublicName) { - return (fir as? FirMemberDeclaration)?.nameOrSpecialName?.identifierOrNullIfSpecial - } - return null -} - diff --git a/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/FirJsStableName.kt b/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/FirJsStableName.kt new file mode 100644 index 00000000000..7332a82e4d6 --- /dev/null +++ b/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/FirJsStableName.kt @@ -0,0 +1,124 @@ +/* + * 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 + +import org.jetbrains.kotlin.descriptors.Visibilities +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClassSymbol +import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration +import org.jetbrains.kotlin.fir.declarations.utils.* +import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol +import org.jetbrains.kotlin.fir.symbols.SymbolInternals +import org.jetbrains.kotlin.fir.symbols.impl.* + +internal data class FirJsStableName( + val name: String, + val symbol: FirBasedSymbol<*>, + val canBeMangled: Boolean, + val isPresentInGeneratedCode: Boolean, +) { + companion object { + private fun hasPublicName(symbol: FirBasedSymbol<*>, session: FirSession): Boolean { + return when (symbol) { + is FirClassLikeSymbol -> !symbol.isLocal + is FirCallableSymbol -> { + val parentClass = symbol.getContainingClassSymbol(session) + if (parentClass != null) { + when (symbol.visibility) { + is Visibilities.Public -> true + is Visibilities.Protected -> !parentClass.isFinal && parentClass.visibility.isPublicAPI + else -> false + } + } else { + !symbol.callableId.isLocal && symbol.effectiveVisibility.publicApi + } + } + else -> false + } + } + + @OptIn(SymbolInternals::class) + fun createStableNameOrNull(symbol: FirBasedSymbol<*>, session: FirSession): FirJsStableName? { + val jsName = symbol.getJsName(session) + if (jsName != null) { + return FirJsStableName(jsName, symbol, false, symbol.isPresentInGeneratedCode(session)) + } + + when (symbol) { + is FirConstructorSymbol -> return null + is FirPropertyAccessorSymbol -> return null + } + + val hasStableNameInJavaScript = when { + symbol.isEffectivelyExternal(session) -> true + symbol.isExportedObject(session) -> true + else -> false + } + + if (hasStableNameInJavaScript || + // TODO: The behavior (using hasPublicName()) is inherited from K1 frontend checks for the Legacy backend. + // However, it is entirely unnecessary in the IR backend. + // This is a trying to replicate the K1 Legacy logic for the sake of consistency, + // but we should redesign and overhaul it later: KT-60554 + // TODO: After that, FirJsStableName.canBeMangled should always be false, + // and all related code can be removed, such as methods: + // - FirJsStableName.hasPublicName(); + // - FirBasedSymbol<*>.doesJSManglingChangeName(); + // - FirJsStableName.shouldClashBeCaughtByCommonFrontendCheck(). + hasPublicName(symbol, session) + ) { + val name = (symbol.fir as? FirMemberDeclaration)?.nameOrSpecialName?.identifierOrNullIfSpecial + if (name != null) { + return FirJsStableName(name, symbol, !hasStableNameInJavaScript, symbol.isPresentInGeneratedCode(session)) + } + } + return null + } + } + + private fun FirBasedSymbol<*>.doesJSManglingChangeName(): Boolean { + return when (this) { + is FirFunctionSymbol<*> -> isExtension || valueParameterSymbols.isNotEmpty() || typeParameterSymbols.isNotEmpty() + is FirPropertySymbol -> isExtension + else -> false + } + } + + private fun shouldClashBeCaughtByCommonFrontendCheck(lhs: FirBasedSymbol<*>, rhs: FirBasedSymbol<*>): Boolean { + return (lhs is FirFunctionSymbol<*> && rhs is FirFunctionSymbol<*>) || + (lhs is FirPropertySymbol && rhs is FirPropertySymbol) || + (lhs is FirClassLikeSymbol<*> && rhs is FirClassLikeSymbol<*>) + } + + private fun isExternalRedeclarable(): Boolean { + return when { + isPresentInGeneratedCode -> false + (symbol as? FirCallableSymbol<*>)?.isFinal == true -> true + else -> symbol is FirClassLikeSymbol<*> + } + } + + fun clashesWith(other: FirJsStableName): Boolean { + return when { + symbol === other.symbol -> false + name != other.name -> false + !isPresentInGeneratedCode && !other.isPresentInGeneratedCode -> false + isExternalRedeclarable() || other.isExternalRedeclarable() -> false + symbol.isActual != other.symbol.isActual -> false + symbol.isExpect != other.symbol.isExpect -> false + canBeMangled && symbol.doesJSManglingChangeName() -> false + other.canBeMangled && other.symbol.doesJSManglingChangeName() -> false + canBeMangled && other.canBeMangled && shouldClashBeCaughtByCommonFrontendCheck(symbol, other.symbol) -> false + else -> true + } + } +} + +internal fun Collection.collectNameClashesWith(name: FirJsStableName) = mapNotNull { next -> + next.takeIf { + next.clashesWith(name) + } +} diff --git a/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/JsDeclarationCheckers.kt b/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/JsDeclarationCheckers.kt index c5c66391eb1..f54f3e51892 100644 --- a/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/JsDeclarationCheckers.kt +++ b/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/JsDeclarationCheckers.kt @@ -32,7 +32,8 @@ object JsDeclarationCheckers : DeclarationCheckers() { FirJsMultipleInheritanceChecker, FirJsDynamicDeclarationChecker, FirJsInheritanceClassChecker, - FirJsExternalInheritorOnlyChecker + FirJsExternalInheritorOnlyChecker, + FirJsNameClashClassMembersChecker ) override val simpleFunctionCheckers: Set @@ -46,4 +47,9 @@ object JsDeclarationCheckers : DeclarationCheckers() { get() = setOf( FirJsPropertyDelegationByDynamicChecker ) + + override val fileCheckers: Set + get() = setOf( + FirJsNameClashFileTopLevelDeclarationsChecker + ) } diff --git a/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/declaration/FirJsBuiltinNameClashChecker.kt b/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/declaration/FirJsBuiltinNameClashChecker.kt index 3fd689829ad..6667dbf287b 100644 --- a/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/declaration/FirJsBuiltinNameClashChecker.kt +++ b/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/declaration/FirJsBuiltinNameClashChecker.kt @@ -11,14 +11,11 @@ import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirBasicDeclarationChecker import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClassSymbol import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors -import org.jetbrains.kotlin.fir.analysis.js.checkers.getStableNameInJavaScript +import org.jetbrains.kotlin.fir.analysis.js.checkers.FirJsStableName import org.jetbrains.kotlin.fir.analysis.js.checkers.isNativeObject import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration import org.jetbrains.kotlin.fir.declarations.FirDeclaration -import org.jetbrains.kotlin.fir.declarations.utils.effectiveVisibility -import org.jetbrains.kotlin.fir.declarations.utils.isLocal -import org.jetbrains.kotlin.fir.declarations.utils.nameOrSpecialName object FirJsBuiltinNameClashChecker : FirBasicDeclarationChecker() { private val PROHIBITED_STATIC_NAMES = setOf("prototype", "length", "\$metadata\$") @@ -32,12 +29,12 @@ object FirJsBuiltinNameClashChecker : FirBasicDeclarationChecker() { return } - val stableName = declaration.symbol.getStableNameInJavaScript(context.session) ?: return + val stableName = FirJsStableName.createStableNameOrNull(declaration.symbol, context.session) ?: return - if (declaration is FirClassLikeDeclaration && stableName in PROHIBITED_STATIC_NAMES) { + if (declaration is FirClassLikeDeclaration && stableName.name in PROHIBITED_STATIC_NAMES) { reporter.reportOn(declaration.source, FirJsErrors.JS_BUILTIN_NAME_CLASH, "Function.$stableName", context) } - if (declaration is FirCallableDeclaration && stableName in PROHIBITED_MEMBER_NAMES) { + if (declaration is FirCallableDeclaration && stableName.name in PROHIBITED_MEMBER_NAMES) { reporter.reportOn(declaration.source, FirJsErrors.JS_BUILTIN_NAME_CLASH, "Object.prototype.$stableName", context) } } diff --git a/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/declaration/FirJsNameCharsChecker.kt b/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/declaration/FirJsNameCharsChecker.kt index 5f85f2a2b0c..163e0684633 100644 --- a/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/declaration/FirJsNameCharsChecker.kt +++ b/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/declaration/FirJsNameCharsChecker.kt @@ -11,8 +11,8 @@ import org.jetbrains.kotlin.diagnostics.reportOn 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.FirJsStableName import org.jetbrains.kotlin.fir.analysis.js.checkers.getJsName -import org.jetbrains.kotlin.fir.analysis.js.checkers.getStableNameInJavaScript import org.jetbrains.kotlin.fir.analysis.js.checkers.isExportedObject import org.jetbrains.kotlin.fir.analysis.js.checkers.sanitizeName import org.jetbrains.kotlin.fir.declarations.FirConstructor @@ -39,8 +39,8 @@ object FirJsNameCharsChecker : FirBasicDeclarationChecker() { return } - val stableName = declaration.symbol.getStableNameInJavaScript(context.session) ?: return - if ((sanitizeName(stableName) != stableName)) { + val stableName = FirJsStableName.createStableNameOrNull(declaration.symbol, context.session) ?: return + if ((sanitizeName(stableName.name) != stableName.name)) { reporter.reportOn(declaration.source, FirJsErrors.NAME_CONTAINS_ILLEGAL_CHARS, context) } } diff --git a/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/declaration/FirJsNameClashClassMembersChecker.kt b/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/declaration/FirJsNameClashClassMembersChecker.kt new file mode 100644 index 00000000000..59c7dae7268 --- /dev/null +++ b/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/declaration/FirJsNameClashClassMembersChecker.kt @@ -0,0 +1,185 @@ +/* + * 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.diagnostics.DiagnosticReporter +import org.jetbrains.kotlin.diagnostics.reportOn +import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext +import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirClassChecker +import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClassSymbol +import org.jetbrains.kotlin.fir.analysis.checkers.unsubstitutedScope +import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors +import org.jetbrains.kotlin.fir.analysis.js.checkers.* +import org.jetbrains.kotlin.fir.analysis.js.checkers.FirJsStableName +import org.jetbrains.kotlin.fir.declarations.FirClass +import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration +import org.jetbrains.kotlin.fir.declarations.utils.isFinal +import org.jetbrains.kotlin.fir.scopes.* +import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirIntersectionCallableSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol +import org.jetbrains.kotlin.utils.addIfNotNull +import org.jetbrains.kotlin.utils.addToStdlib.popLast + +object FirJsNameClashClassMembersChecker : FirClassChecker() { + private class StableNamesCollector { + val jsStableNames = mutableSetOf() + val overrideIntersections = hashMapOf, HashSet>>() + + private val allSymbols = mutableSetOf>() + + private fun FirTypeScope.collectOverriddenLeaves(classMemberSymbol: FirCallableSymbol<*>): Set> { + val visitedSymbols = hashSetOf(classMemberSymbol) + val symbolsToProcess = mutableListOf(classMemberSymbol) + val leaves = mutableSetOf>() + while (symbolsToProcess.isNotEmpty()) { + val processingSymbol = symbolsToProcess.popLast() + val overriddenMembers = getDirectOverriddenMembers(processingSymbol, true) + for (overriddenMember in overriddenMembers) { + if (visitedSymbols.add(overriddenMember)) { + symbolsToProcess.add(overriddenMember) + } + } + if (overriddenMembers.isEmpty()) { + leaves.add(processingSymbol) + } + } + return leaves + } + + private fun MutableSet.addStableJavaScriptName( + targetSymbol: FirCallableSymbol<*>?, + overriddenSymbol: FirCallableSymbol<*>?, + context: CheckerContext, + ) { + val stableName = when { + targetSymbol == null || overriddenSymbol == null -> return + (targetSymbol as? FirConstructorSymbol)?.isPrimary == true -> return + !overriddenSymbol.isPresentInGeneratedCode(context.session) && overriddenSymbol.isFinal -> return + else -> FirJsStableName.createStableNameOrNull(overriddenSymbol, context.session) ?: return + } + + if (stableName.isPresentInGeneratedCode) { + add(stableName.copy(symbol = targetSymbol)) + } else { + val inheritedExternalName = stableName.copy( + symbol = targetSymbol, + canBeMangled = false, + isPresentInGeneratedCode = targetSymbol.isPresentInGeneratedCode(context.session) + ) + add(inheritedExternalName) + } + } + + private fun MutableSet.addAllStableJavaScriptNames( + targetSymbol: FirCallableSymbol<*>, + overriddenSymbol: FirCallableSymbol<*>, + context: CheckerContext, + ) { + addStableJavaScriptName(targetSymbol, overriddenSymbol, context) + if (targetSymbol is FirPropertySymbol && overriddenSymbol is FirPropertySymbol) { + addStableJavaScriptName(targetSymbol.getterSymbol, overriddenSymbol.getterSymbol, context) + addStableJavaScriptName(targetSymbol.setterSymbol, overriddenSymbol.setterSymbol, context) + } + } + + fun addAllSymbolsFrom(symbols: Collection>) { + for (symbol in symbols) { + when (symbol) { + is FirIntersectionCallableSymbol -> { + addAllSymbolsFrom(symbol.intersections) + for (intersectedSymbol in symbol.intersections) { + overrideIntersections.getOrPut(intersectedSymbol) { hashSetOf() }.addAll(symbol.intersections) + } + } + else -> allSymbols.add(symbol) + } + } + } + + fun processStableJavaScriptNamesForMembers(declaration: FirClass, context: CheckerContext) { + for (classMember in declaration.declarations) { + if (classMember is FirClassLikeDeclaration) { + jsStableNames.addIfNotNull(FirJsStableName.createStableNameOrNull(classMember.symbol, context.session)) + } + } + + val scope = declaration.symbol.unsubstitutedScope(context) + + addAllSymbolsFrom(scope.collectAllFunctions()) + addAllSymbolsFrom(scope.collectAllProperties()) + + for (callableMemberSymbol in allSymbols) { + val overriddenLeaves = scope.collectOverriddenLeaves(callableMemberSymbol) + for (symbol in overriddenLeaves) { + jsStableNames.addAllStableJavaScriptNames(callableMemberSymbol, symbol, context) + } + } + } + } + + private fun List.filterFakeOverrideNames(declaration: FirClass, context: CheckerContext) = filterTo(mutableSetOf()) { + it.symbol.getContainingClassSymbol(context.session) != declaration.symbol + } + + private data class ClashedSymbol(val symbol: FirBasedSymbol<*>, val clashedWith: List>) + + private fun List.collectNonFakeOverrideClashes(isFakeOverrideName: (FirJsStableName) -> Boolean): List { + return buildList { + for (stableName in this@collectNonFakeOverrideClashes) { + var clashed = collectNameClashesWith(stableName) + if (isFakeOverrideName(stableName)) { + // Do not check for clashes between fake overrides here. + // Such clashes will be checked with JS_FAKE_NAME_CLASH. + clashed = clashed.filter { !isFakeOverrideName(it) } + } + if (clashed.isNotEmpty()) { + add(ClashedSymbol(stableName.symbol, clashed.map { it.symbol })) + } + } + } + } + + private fun Set.findFirstFakeOverrideClash(stableNameCollector: StableNamesCollector): ClashedSymbol? { + for (stableName in this) { + val intersectedSymbols = stableNameCollector.overrideIntersections[stableName.symbol] ?: emptySet() + val clashed = collectNameClashesWith(stableName).filter { + // intersected fake override symbols are not clashed + it.symbol !in intersectedSymbols + } + if (clashed.isNotEmpty()) { + return ClashedSymbol(stableName.symbol, clashed.map { it.symbol }) + } + } + return null + } + + override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) { + if (!declaration.symbol.isPresentInGeneratedCode(context.session)) { + return + } + + val stableNameCollector = StableNamesCollector() + stableNameCollector.processStableJavaScriptNamesForMembers(declaration, context) + + val membersGroupedByName = stableNameCollector.jsStableNames.groupBy { it.name } + + for ((name, stableNames) in membersGroupedByName.entries) { + val fakeOverrideStableNames = stableNames.filterFakeOverrideNames(declaration, context) + + val nonFakeOverrideClashes = stableNames.collectNonFakeOverrideClashes { it in fakeOverrideStableNames } + for ((symbol, clashedWith) in nonFakeOverrideClashes) { + reporter.reportOn(symbol.source ?: declaration.source, FirJsErrors.JS_NAME_CLASH, name, clashedWith, context) + } + + fakeOverrideStableNames.findFirstFakeOverrideClash(stableNameCollector)?.let { (fakeOverrideSymbol, clashedWith) -> + reporter.reportOn(declaration.source, FirJsErrors.JS_FAKE_NAME_CLASH, name, fakeOverrideSymbol, clashedWith, context) + } + } + } +} diff --git a/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/declaration/FirJsNameClashFileTopLevelDeclarationsChecker.kt b/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/declaration/FirJsNameClashFileTopLevelDeclarationsChecker.kt new file mode 100644 index 00000000000..1543cd5f815 --- /dev/null +++ b/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/declaration/FirJsNameClashFileTopLevelDeclarationsChecker.kt @@ -0,0 +1,58 @@ +/* + * 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.diagnostics.DiagnosticReporter +import org.jetbrains.kotlin.diagnostics.reportOn +import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext +import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirFileChecker +import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors +import org.jetbrains.kotlin.fir.analysis.js.checkers.FirJsStableName +import org.jetbrains.kotlin.fir.analysis.js.checkers.collectNameClashesWith +import org.jetbrains.kotlin.fir.declarations.* +import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol + +object FirJsNameClashFileTopLevelDeclarationsChecker : FirFileChecker() { + private fun MutableMap>.addStableName( + symbol: FirBasedSymbol<*>, + context: CheckerContext + ) { + val stableName = FirJsStableName.createStableNameOrNull(symbol, context.session) + if (stableName != null) { + getOrPut(stableName.name) { mutableListOf() }.add(stableName) + } + if (symbol is FirPropertySymbol) { + symbol.getterSymbol?.let { getter -> addStableName(getter, context) } + symbol.setterSymbol?.let { setter -> addStableName(setter, context) } + } + } + + override fun check(declaration: FirFile, context: CheckerContext, reporter: DiagnosticReporter) { + val topLevelDeclarationsWithStableName = mutableMapOf>() + for (topLevelDeclaration in declaration.declarations) { + if (topLevelDeclaration is FirTypeAlias) { + // Skip type aliases since they cannot be external, cannot be exported to JavaScript, and cannot be marked with @JsName. + // Furthermore, in the generated JavaScript code, all type alias declarations are removed, + // and their usages are replaced with the aliased types. + continue + } + topLevelDeclarationsWithStableName.addStableName(topLevelDeclaration.symbol, context) + if (topLevelDeclaration is FirClass) { + for (classConstructor in topLevelDeclaration.constructors(context.session)) { + topLevelDeclarationsWithStableName.addStableName(classConstructor, context) + } + } + } + for ((name, stableNames) in topLevelDeclarationsWithStableName.entries) { + for (symbol in stableNames) { + val clashed = stableNames.collectNameClashesWith(symbol).takeIf { it.isNotEmpty() } ?: continue + val source = symbol.symbol.source ?: declaration.source + reporter.reportOn(source, FirJsErrors.JS_NAME_CLASH, name, clashed.map { it.symbol }, context) + } + } + } +} diff --git a/compiler/testData/codegen/box/callableReference/function/overloadedFunVsVal.kt b/compiler/testData/codegen/box/callableReference/function/overloadedFunVsVal.kt index 445fd1f61aa..3c83b51d84a 100644 --- a/compiler/testData/codegen/box/callableReference/function/overloadedFunVsVal.kt +++ b/compiler/testData/codegen/box/callableReference/function/overloadedFunVsVal.kt @@ -1,5 +1,6 @@ // IGNORE_BACKEND_K1: WASM // IGNORE_BACKEND_K1: JS_IR, JS_IR_ES6 +// IGNORE_BACKEND_K2: JS_IR, JS_IR_ES6 // TODO: muted automatically, investigate should it be ran for JS or not // IGNORE_BACKEND: JS diff --git a/compiler/testData/codegen/box/controlStructures/forLoopMemberExtensionNext.kt b/compiler/testData/codegen/box/controlStructures/forLoopMemberExtensionNext.kt index a089422a8a1..da7c674194a 100644 --- a/compiler/testData/codegen/box/controlStructures/forLoopMemberExtensionNext.kt +++ b/compiler/testData/codegen/box/controlStructures/forLoopMemberExtensionNext.kt @@ -1,4 +1,5 @@ // IGNORE_BACKEND_K1: JS_IR, JS_IR_ES6, WASM +// IGNORE_BACKEND_K2: JS_IR, JS_IR_ES6 // TODO: muted automatically, investigate should it be ran for JS or not // IGNORE_BACKEND: JS diff --git a/compiler/testData/codegen/box/package/invokespecial.kt b/compiler/testData/codegen/box/package/invokespecial.kt index 9076087be86..2a92f3e4090 100644 --- a/compiler/testData/codegen/box/package/invokespecial.kt +++ b/compiler/testData/codegen/box/package/invokespecial.kt @@ -1,5 +1,6 @@ // IGNORE_BACKEND_K1: WASM // IGNORE_BACKEND_K1: JS_IR, JS_IR_ES6 +// IGNORE_BACKEND_K2: JS_IR, JS_IR_ES6 // TODO: muted automatically, investigate should it be ran for JS or not // IGNORE_BACKEND: JS diff --git a/compiler/testData/codegen/box/properties/accessToPrivateSetter.kt b/compiler/testData/codegen/box/properties/accessToPrivateSetter.kt index 9947561bf32..286b527f3b2 100644 --- a/compiler/testData/codegen/box/properties/accessToPrivateSetter.kt +++ b/compiler/testData/codegen/box/properties/accessToPrivateSetter.kt @@ -1,5 +1,6 @@ // IGNORE_BACKEND_K1: WASM // IGNORE_BACKEND_K1: JS_IR, JS_IR_ES6 +// IGNORE_BACKEND_K2: JS_IR, JS_IR_ES6 // TODO: muted automatically, investigate should it be ran for JS or not // IGNORE_BACKEND: JS diff --git a/compiler/testData/codegen/box/smartCasts/lambdaArgumentWithoutType.kt b/compiler/testData/codegen/box/smartCasts/lambdaArgumentWithoutType.kt index d9019ef5127..c987d4f3542 100644 --- a/compiler/testData/codegen/box/smartCasts/lambdaArgumentWithoutType.kt +++ b/compiler/testData/codegen/box/smartCasts/lambdaArgumentWithoutType.kt @@ -1,5 +1,6 @@ // IGNORE_BACKEND_K1: WASM // IGNORE_BACKEND_K1: JS_IR, JS_IR_ES6 +// IGNORE_BACKEND_K2: JS_IR, JS_IR_ES6 // TODO: muted automatically, investigate should it be ran for JS or not // IGNORE_BACKEND: JS diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/name/bridgeClash.fir.kt b/compiler/testData/diagnostics/testsWithJsStdLib/name/bridgeClash.fir.kt deleted file mode 100644 index 401f7b6dac2..00000000000 --- a/compiler/testData/diagnostics/testsWithJsStdLib/name/bridgeClash.fir.kt +++ /dev/null @@ -1,18 +0,0 @@ -interface I { - fun foo() -} - -interface J { - @JsName("bar") - fun foo() -} - -interface K : I, J { - override fun foo() -} - -interface L : K { - override fun foo() - - fun bar() -} diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/name/bridgeClash.kt b/compiler/testData/diagnostics/testsWithJsStdLib/name/bridgeClash.kt index 6a9fb53452e..3eaca72f1d0 100644 --- a/compiler/testData/diagnostics/testsWithJsStdLib/name/bridgeClash.kt +++ b/compiler/testData/diagnostics/testsWithJsStdLib/name/bridgeClash.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL interface I { fun foo() } diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/name/classAndFunction.fir.kt b/compiler/testData/diagnostics/testsWithJsStdLib/name/classAndFunction.fir.kt deleted file mode 100644 index f4b67b3835c..00000000000 --- a/compiler/testData/diagnostics/testsWithJsStdLib/name/classAndFunction.fir.kt +++ /dev/null @@ -1,5 +0,0 @@ -package foo - -class A(val x: Int) - -fun A() {} diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/name/classAndFunction.kt b/compiler/testData/diagnostics/testsWithJsStdLib/name/classAndFunction.kt index 0a4bcc34e5c..1fd8392c5f4 100644 --- a/compiler/testData/diagnostics/testsWithJsStdLib/name/classAndFunction.kt +++ b/compiler/testData/diagnostics/testsWithJsStdLib/name/classAndFunction.kt @@ -1,5 +1,6 @@ +// FIR_IDENTICAL package foo class A(val x: Int) -fun A() {} \ No newline at end of file +fun A() {} diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/name/classLevelMethodAndProperty.fir.kt b/compiler/testData/diagnostics/testsWithJsStdLib/name/classLevelMethodAndProperty.fir.kt deleted file mode 100644 index 580a301663d..00000000000 --- a/compiler/testData/diagnostics/testsWithJsStdLib/name/classLevelMethodAndProperty.fir.kt +++ /dev/null @@ -1,7 +0,0 @@ -package foo - -class A { - fun bar() = 23 - - val bar = 23 -} diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/name/classLevelMethodAndProperty.kt b/compiler/testData/diagnostics/testsWithJsStdLib/name/classLevelMethodAndProperty.kt index 64795442834..b7cf660b946 100644 --- a/compiler/testData/diagnostics/testsWithJsStdLib/name/classLevelMethodAndProperty.kt +++ b/compiler/testData/diagnostics/testsWithJsStdLib/name/classLevelMethodAndProperty.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL package foo class A { diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/name/conflictingNamesFromSuperclass.fir.kt b/compiler/testData/diagnostics/testsWithJsStdLib/name/conflictingNamesFromSuperclass.fir.kt deleted file mode 100644 index ff85da4a2e5..00000000000 --- a/compiler/testData/diagnostics/testsWithJsStdLib/name/conflictingNamesFromSuperclass.fir.kt +++ /dev/null @@ -1,23 +0,0 @@ -interface A { - @JsName("foo") fun f() -} - -interface B { - @JsName("foo") fun g() -} - -class C : A, B { - override fun f() {} - - override fun g() {} -} - -abstract class D : A, B - -open class E { - open fun f() {} - - open fun g() {} -} - -class F : E(), A, B diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/name/conflictingNamesFromSuperclass.kt b/compiler/testData/diagnostics/testsWithJsStdLib/name/conflictingNamesFromSuperclass.kt index f7f5e18372f..56fc897e7be 100644 --- a/compiler/testData/diagnostics/testsWithJsStdLib/name/conflictingNamesFromSuperclass.kt +++ b/compiler/testData/diagnostics/testsWithJsStdLib/name/conflictingNamesFromSuperclass.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL interface A { @JsName("foo") fun f() } diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/name/extensionPropertyAndMethod.fir.kt b/compiler/testData/diagnostics/testsWithJsStdLib/name/extensionPropertyAndMethod.fir.kt index 6e763f81fc0..56237c5fdb8 100644 --- a/compiler/testData/diagnostics/testsWithJsStdLib/name/extensionPropertyAndMethod.fir.kt +++ b/compiler/testData/diagnostics/testsWithJsStdLib/name/extensionPropertyAndMethod.fir.kt @@ -1,3 +1,6 @@ +// FIR_DIFFERENCE +// This case is only relevant for the JS Legacy BE and is not applicable to the JS IR backend, +// as the IR BE can resolve such name collisions. package foo class A diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/name/extensionPropertyAndMethod.kt b/compiler/testData/diagnostics/testsWithJsStdLib/name/extensionPropertyAndMethod.kt index e07e0455f05..fc43d5b1d5f 100644 --- a/compiler/testData/diagnostics/testsWithJsStdLib/name/extensionPropertyAndMethod.kt +++ b/compiler/testData/diagnostics/testsWithJsStdLib/name/extensionPropertyAndMethod.kt @@ -1,3 +1,6 @@ +// FIR_DIFFERENCE +// This case is only relevant for the JS Legacy BE and is not applicable to the JS IR backend, +// as the IR BE can resolve such name collisions. package foo class A @@ -5,4 +8,4 @@ class A fun A.get_bar() = 23 val A.bar: Int - get() = 42 \ No newline at end of file + get() = 42 diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/name/jsNameAndOverridden.fir.kt b/compiler/testData/diagnostics/testsWithJsStdLib/name/jsNameAndOverridden.fir.kt deleted file mode 100644 index df974383a3a..00000000000 --- a/compiler/testData/diagnostics/testsWithJsStdLib/name/jsNameAndOverridden.fir.kt +++ /dev/null @@ -1,9 +0,0 @@ -package foo - -open class Super { - fun foo() = 23 -} - -class Sub : Super() { - @JsName("foo") fun bar() = 42 -} diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/name/jsNameAndOverridden.kt b/compiler/testData/diagnostics/testsWithJsStdLib/name/jsNameAndOverridden.kt index cc689dd18c2..838977073f5 100644 --- a/compiler/testData/diagnostics/testsWithJsStdLib/name/jsNameAndOverridden.kt +++ b/compiler/testData/diagnostics/testsWithJsStdLib/name/jsNameAndOverridden.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL package foo open class Super { diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/name/jsNameClash.fir.kt b/compiler/testData/diagnostics/testsWithJsStdLib/name/jsNameClash.fir.kt deleted file mode 100644 index 3f0fac6f1bc..00000000000 --- a/compiler/testData/diagnostics/testsWithJsStdLib/name/jsNameClash.fir.kt +++ /dev/null @@ -1,5 +0,0 @@ -package foo - -@JsName("x") fun foo(x: Int) = x - -@JsName("x") fun bar() = 42 diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/name/jsNameClash.kt b/compiler/testData/diagnostics/testsWithJsStdLib/name/jsNameClash.kt index 6eb24057fed..6bba772ac1c 100644 --- a/compiler/testData/diagnostics/testsWithJsStdLib/name/jsNameClash.kt +++ b/compiler/testData/diagnostics/testsWithJsStdLib/name/jsNameClash.kt @@ -1,5 +1,6 @@ +// FIR_IDENTICAL package foo @JsName("x") fun foo(x: Int) = x -@JsName("x") fun bar() = 42 \ No newline at end of file +@JsName("x") fun bar() = 42 diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/name/jsNameClashWithDefault.fir.kt b/compiler/testData/diagnostics/testsWithJsStdLib/name/jsNameClashWithDefault.fir.kt deleted file mode 100644 index e691a11a05d..00000000000 --- a/compiler/testData/diagnostics/testsWithJsStdLib/name/jsNameClashWithDefault.fir.kt +++ /dev/null @@ -1,5 +0,0 @@ -package foo - -@JsName("bar") fun foo(x: Int) = x - -fun bar() = 42 diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/name/jsNameClashWithDefault.kt b/compiler/testData/diagnostics/testsWithJsStdLib/name/jsNameClashWithDefault.kt index 9f677efdfca..26dea35fe74 100644 --- a/compiler/testData/diagnostics/testsWithJsStdLib/name/jsNameClashWithDefault.kt +++ b/compiler/testData/diagnostics/testsWithJsStdLib/name/jsNameClashWithDefault.kt @@ -1,5 +1,6 @@ +// FIR_IDENTICAL package foo @JsName("bar") fun foo(x: Int) = x -fun bar() = 42 \ No newline at end of file +fun bar() = 42 diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/name/jsNameOnAccessors.fir.kt b/compiler/testData/diagnostics/testsWithJsStdLib/name/jsNameOnAccessors.fir.kt index eebd6729039..50ad8ecca19 100644 --- a/compiler/testData/diagnostics/testsWithJsStdLib/name/jsNameOnAccessors.fir.kt +++ b/compiler/testData/diagnostics/testsWithJsStdLib/name/jsNameOnAccessors.fir.kt @@ -2,6 +2,6 @@ package foo class A { var x: Int - @JsName("xx") get() = 0 - @JsName("xx") set(value) {} + @JsName("xx") get() = 0 + @JsName("xx") set(value) {} } diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/name/methodAndMethod.fir.kt b/compiler/testData/diagnostics/testsWithJsStdLib/name/methodAndMethod.fir.kt index 3d0ed276fa9..2ec6d3a83c3 100644 --- a/compiler/testData/diagnostics/testsWithJsStdLib/name/methodAndMethod.fir.kt +++ b/compiler/testData/diagnostics/testsWithJsStdLib/name/methodAndMethod.fir.kt @@ -1,3 +1,6 @@ +// FIR_DIFFERENCE +// This case is only relevant for the JS Legacy BE and is not applicable to the JS IR backend, +// as the IR BE can resolve such name collisions. Furthermore, the IR BE mangles names differently. package foo fun bar(x: Int) = x diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/name/methodAndMethod.kt b/compiler/testData/diagnostics/testsWithJsStdLib/name/methodAndMethod.kt index 9b4b08a8656..32088ef4c7c 100644 --- a/compiler/testData/diagnostics/testsWithJsStdLib/name/methodAndMethod.kt +++ b/compiler/testData/diagnostics/testsWithJsStdLib/name/methodAndMethod.kt @@ -1,5 +1,8 @@ +// FIR_DIFFERENCE +// This case is only relevant for the JS Legacy BE and is not applicable to the JS IR backend, +// as the IR BE can resolve such name collisions. Furthermore, the IR BE mangles names differently. package foo fun bar(x: Int) = x -fun `bar_za3lpa$`() = 42 \ No newline at end of file +fun `bar_za3lpa$`() = 42 diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/name/nameSwapInOverride.fir.kt b/compiler/testData/diagnostics/testsWithJsStdLib/name/nameSwapInOverride.fir.kt deleted file mode 100644 index 66002f98bf4..00000000000 --- a/compiler/testData/diagnostics/testsWithJsStdLib/name/nameSwapInOverride.fir.kt +++ /dev/null @@ -1,21 +0,0 @@ -interface I { - @JsName("bar") - fun foo() - - @JsName("foo") - fun bar() -} - -interface J { - fun foo() - - fun bar() -} - -class A : I, J { - // Duplicate diagnostics are expected here, since `bar()` function gets both `foo` and `bar` names and clashes with both - // names of `foo()` function. - override fun bar() {} - - override fun foo() {} -} diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/name/nameSwapInOverride.kt b/compiler/testData/diagnostics/testsWithJsStdLib/name/nameSwapInOverride.kt index 6de82abc7aa..1411adbde69 100644 --- a/compiler/testData/diagnostics/testsWithJsStdLib/name/nameSwapInOverride.kt +++ b/compiler/testData/diagnostics/testsWithJsStdLib/name/nameSwapInOverride.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL interface I { @JsName("bar") fun foo() diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/name/overrideOverloadedNativeFunction.fir.kt b/compiler/testData/diagnostics/testsWithJsStdLib/name/overrideOverloadedNativeFunction.fir.kt deleted file mode 100644 index c28351e23d6..00000000000 --- a/compiler/testData/diagnostics/testsWithJsStdLib/name/overrideOverloadedNativeFunction.fir.kt +++ /dev/null @@ -1,9 +0,0 @@ -external open class A { - open fun f(x: Int): Unit - - open fun f(x: String): Unit -} - -class InheritClass : A() { - override fun f(x: Int): Unit { } -} diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/name/overrideOverloadedNativeFunction.kt b/compiler/testData/diagnostics/testsWithJsStdLib/name/overrideOverloadedNativeFunction.kt index a7c8c194498..94fb9fe2c0e 100644 --- a/compiler/testData/diagnostics/testsWithJsStdLib/name/overrideOverloadedNativeFunction.kt +++ b/compiler/testData/diagnostics/testsWithJsStdLib/name/overrideOverloadedNativeFunction.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL external open class A { open fun f(x: Int): Unit diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/name/packageAndMethod.fir.kt b/compiler/testData/diagnostics/testsWithJsStdLib/name/packageAndMethod.fir.kt index 154ce6837b3..df229ea5807 100644 --- a/compiler/testData/diagnostics/testsWithJsStdLib/name/packageAndMethod.fir.kt +++ b/compiler/testData/diagnostics/testsWithJsStdLib/name/packageAndMethod.fir.kt @@ -1,3 +1,6 @@ +// FIR_DIFFERENCE +// This case can't be checked using FIR. It is checked later on klib serialization. + // FILE: foo.kt package foo diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/name/packageAndMethod.kt b/compiler/testData/diagnostics/testsWithJsStdLib/name/packageAndMethod.kt index 095ecacee8d..6fe6489bd0d 100644 --- a/compiler/testData/diagnostics/testsWithJsStdLib/name/packageAndMethod.kt +++ b/compiler/testData/diagnostics/testsWithJsStdLib/name/packageAndMethod.kt @@ -1,3 +1,6 @@ +// FIR_DIFFERENCE +// This case can't be checked using FIR. It is checked later on klib serialization. + // FILE: foo.kt package foo diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/name/packageAndProperty.fir.kt b/compiler/testData/diagnostics/testsWithJsStdLib/name/packageAndProperty.fir.kt index 4e8b6cbda3c..060ad3f4bc0 100644 --- a/compiler/testData/diagnostics/testsWithJsStdLib/name/packageAndProperty.fir.kt +++ b/compiler/testData/diagnostics/testsWithJsStdLib/name/packageAndProperty.fir.kt @@ -1,3 +1,6 @@ +// FIR_DIFFERENCE +// This case can't be checked using FIR. It is checked later on klib serialization. + // FILE: foo.kt package foo diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/name/packageAndProperty.kt b/compiler/testData/diagnostics/testsWithJsStdLib/name/packageAndProperty.kt index 133bb4ea171..ec84fa2a6a4 100644 --- a/compiler/testData/diagnostics/testsWithJsStdLib/name/packageAndProperty.kt +++ b/compiler/testData/diagnostics/testsWithJsStdLib/name/packageAndProperty.kt @@ -1,3 +1,6 @@ +// FIR_DIFFERENCE +// This case can't be checked using FIR. It is checked later on klib serialization. + // FILE: foo.kt package foo diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/name/privateJsNameClash.fir.kt b/compiler/testData/diagnostics/testsWithJsStdLib/name/privateJsNameClash.fir.kt deleted file mode 100644 index bad5f53fc42..00000000000 --- a/compiler/testData/diagnostics/testsWithJsStdLib/name/privateJsNameClash.fir.kt +++ /dev/null @@ -1,5 +0,0 @@ -package foo - -@JsName("bar") private fun foo(x: Int) = x - -fun bar() = 42 diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/name/privateJsNameClash.kt b/compiler/testData/diagnostics/testsWithJsStdLib/name/privateJsNameClash.kt index 21dda09a4dc..d64fedab07a 100644 --- a/compiler/testData/diagnostics/testsWithJsStdLib/name/privateJsNameClash.kt +++ b/compiler/testData/diagnostics/testsWithJsStdLib/name/privateJsNameClash.kt @@ -1,5 +1,6 @@ +// FIR_IDENTICAL package foo @JsName("bar") private fun foo(x: Int) = x -fun bar() = 42 \ No newline at end of file +fun bar() = 42 diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/name/propertyAndMethodInImplementor.fir.kt b/compiler/testData/diagnostics/testsWithJsStdLib/name/propertyAndMethodInImplementor.fir.kt deleted file mode 100644 index 8123284e4d6..00000000000 --- a/compiler/testData/diagnostics/testsWithJsStdLib/name/propertyAndMethodInImplementor.fir.kt +++ /dev/null @@ -1,9 +0,0 @@ -package foo - -interface I { - fun foo() = 23 -} - -class Sub : I { - var foo = 42 -} diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/name/propertyAndMethodInImplementor.kt b/compiler/testData/diagnostics/testsWithJsStdLib/name/propertyAndMethodInImplementor.kt index 2c65608fb7b..39121880808 100644 --- a/compiler/testData/diagnostics/testsWithJsStdLib/name/propertyAndMethodInImplementor.kt +++ b/compiler/testData/diagnostics/testsWithJsStdLib/name/propertyAndMethodInImplementor.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL package foo interface I { diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/name/propertyAndMethodInSubclass.fir.kt b/compiler/testData/diagnostics/testsWithJsStdLib/name/propertyAndMethodInSubclass.fir.kt deleted file mode 100644 index a18d903cc5d..00000000000 --- a/compiler/testData/diagnostics/testsWithJsStdLib/name/propertyAndMethodInSubclass.fir.kt +++ /dev/null @@ -1,9 +0,0 @@ -package foo - -open class Super { - val foo = 23 -} - -class Sub : Super() { - fun foo() = 42 -} diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/name/propertyAndMethodInSubclass.kt b/compiler/testData/diagnostics/testsWithJsStdLib/name/propertyAndMethodInSubclass.kt index fdc6a30ffc7..824aa4ae423 100644 --- a/compiler/testData/diagnostics/testsWithJsStdLib/name/propertyAndMethodInSubclass.kt +++ b/compiler/testData/diagnostics/testsWithJsStdLib/name/propertyAndMethodInSubclass.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL package foo open class Super { diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/name/topLevelMethodAndJsNameConstructor.fir.kt b/compiler/testData/diagnostics/testsWithJsStdLib/name/topLevelMethodAndJsNameConstructor.fir.kt deleted file mode 100644 index 051449586e8..00000000000 --- a/compiler/testData/diagnostics/testsWithJsStdLib/name/topLevelMethodAndJsNameConstructor.fir.kt +++ /dev/null @@ -1,7 +0,0 @@ -package foo - -class A(val x: String) { - @JsName("aa") constructor(x: Int) : this("int $x") -} - -fun aa() {} diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/name/topLevelMethodAndJsNameConstructor.kt b/compiler/testData/diagnostics/testsWithJsStdLib/name/topLevelMethodAndJsNameConstructor.kt index 3728c2791d8..5c98482653d 100644 --- a/compiler/testData/diagnostics/testsWithJsStdLib/name/topLevelMethodAndJsNameConstructor.kt +++ b/compiler/testData/diagnostics/testsWithJsStdLib/name/topLevelMethodAndJsNameConstructor.kt @@ -1,7 +1,8 @@ +// FIR_IDENTICAL package foo class A(val x: String) { @JsName("aa") constructor(x: Int) : this("int $x") } -fun aa() {} \ No newline at end of file +fun aa() {} diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/name/topLevelMethodAndProperty.fir.kt b/compiler/testData/diagnostics/testsWithJsStdLib/name/topLevelMethodAndProperty.fir.kt deleted file mode 100644 index 361aa200e2f..00000000000 --- a/compiler/testData/diagnostics/testsWithJsStdLib/name/topLevelMethodAndProperty.fir.kt +++ /dev/null @@ -1,5 +0,0 @@ -package foo - -fun bar() = 23 - -val bar = 32 diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/name/topLevelMethodAndProperty.kt b/compiler/testData/diagnostics/testsWithJsStdLib/name/topLevelMethodAndProperty.kt index 815fd69cad0..dbf66155d3f 100644 --- a/compiler/testData/diagnostics/testsWithJsStdLib/name/topLevelMethodAndProperty.kt +++ b/compiler/testData/diagnostics/testsWithJsStdLib/name/topLevelMethodAndProperty.kt @@ -1,5 +1,6 @@ +// FIR_IDENTICAL package foo fun bar() = 23 -val bar = 32 \ No newline at end of file +val bar = 32 diff --git a/compiler/testData/ir/irText/classes/declarationOrder.kt b/compiler/testData/ir/irText/classes/declarationOrder.kt index 2dfd1a340c3..174ed915414 100644 --- a/compiler/testData/ir/irText/classes/declarationOrder.kt +++ b/compiler/testData/ir/irText/classes/declarationOrder.kt @@ -1,6 +1,7 @@ // FIR_IDENTICAL // SKIP_KLIB_TEST // IGNORE_BACKEND_K1: JS_IR +// IGNORE_BACKEND_K2: JS_IR // Ignore reason: there is a js name clash between function `a()` and property `a` package test