[JS FIR] Support JS_BUILTIN_NAME_CLASH diagnostic
^KT-59391 Fixed
This commit is contained in:
committed by
Space Team
parent
f061215ee9
commit
37c8ec1e51
+3
@@ -54,6 +54,9 @@ object JS_DIAGNOSTICS_LIST : DiagnosticList("FirJsErrors") {
|
||||
val JS_NAME_ON_PRIMARY_CONSTRUCTOR_PROHIBITED by error<KtElement>()
|
||||
val JS_NAME_ON_ACCESSOR_AND_PROPERTY by error<KtElement>()
|
||||
val JS_NAME_PROHIBITED_FOR_EXTENSION_PROPERTY by error<KtElement>()
|
||||
val JS_BUILTIN_NAME_CLASH by error<KtElement>(PositioningStrategy.DECLARATION_SIGNATURE_OR_DEFAULT) {
|
||||
parameter<String>("name")
|
||||
}
|
||||
}
|
||||
|
||||
val SUPERTYPES by object : DiagnosticGroup("Supertypes") {
|
||||
|
||||
+1
@@ -50,6 +50,7 @@ object FirJsErrors {
|
||||
val JS_NAME_ON_PRIMARY_CONSTRUCTOR_PROHIBITED by error0<KtElement>()
|
||||
val JS_NAME_ON_ACCESSOR_AND_PROPERTY by error0<KtElement>()
|
||||
val JS_NAME_PROHIBITED_FOR_EXTENSION_PROPERTY by error0<KtElement>()
|
||||
val JS_BUILTIN_NAME_CLASH by error1<KtElement, String>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT)
|
||||
|
||||
// Supertypes
|
||||
val WRONG_MULTIPLE_INHERITANCE by error1<KtElement, FirCallableSymbol<*>>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT)
|
||||
|
||||
+7
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.ENUM_CLASS_I
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.EXTERNAL_INTERFACE_AS_REIFIED_TYPE_ARGUMENT
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.JS_EXTERNAL_INHERITORS_ONLY
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.INLINE_EXTERNAL_DECLARATION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.JS_BUILTIN_NAME_CLASH
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.JS_EXTERNAL_ARGUMENT
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.JS_MODULE_PROHIBITED_ON_NON_NATIVE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.JS_MODULE_PROHIBITED_ON_VAR
|
||||
@@ -193,6 +194,12 @@ object FirJsErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
|
||||
FirDiagnosticRenderers.RENDER_TYPE
|
||||
)
|
||||
map.put(JS_NAME_PROHIBITED_FOR_EXTENSION_PROPERTY, "@JsName is prohibited for extension properties")
|
||||
map.put(
|
||||
JS_BUILTIN_NAME_CLASH,
|
||||
"JavaScript name generated for this declaration clashes with built-in declaration {0}",
|
||||
CommonRenderers.STRING
|
||||
)
|
||||
|
||||
map.put(JS_NAME_IS_NOT_ON_ALL_ACCESSORS, "@JsName should be on all the property accessors")
|
||||
map.put(JS_NAME_PROHIBITED_FOR_NAMED_NATIVE, "@JsName is prohibited for external declaration with explicit name")
|
||||
map.put(JS_NAME_PROHIBITED_FOR_OVERRIDE, "@JsName is prohibited for overridden members")
|
||||
|
||||
+36
@@ -10,6 +10,7 @@ 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
|
||||
@@ -161,3 +162,38 @@ internal fun getRootClassLikeSymbolOrSelf(symbol: FirBasedSymbol<*>, session: Fi
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -23,6 +23,7 @@ object JsDeclarationCheckers : DeclarationCheckers() {
|
||||
FirJsNameChecker,
|
||||
FirJsExportAnnotationChecker,
|
||||
FirJsExportDeclarationChecker,
|
||||
FirJsBuiltinNameClashChecker
|
||||
)
|
||||
|
||||
override val classCheckers: Set<FirClassChecker>
|
||||
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.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.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\$")
|
||||
private val PROHIBITED_MEMBER_NAMES = setOf("constructor")
|
||||
|
||||
override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
if (declaration.symbol.isNativeObject(context.session)) {
|
||||
return
|
||||
}
|
||||
if (declaration.getContainingClassSymbol(context.session) == null) {
|
||||
return
|
||||
}
|
||||
|
||||
val stableName = declaration.symbol.getStableNameInJavaScript(context.session) ?: return
|
||||
|
||||
if (declaration is FirClassLikeDeclaration && stableName 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) {
|
||||
reporter.reportOn(declaration.source, FirJsErrors.JS_BUILTIN_NAME_CLASH, "Object.prototype.$stableName", context)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user