[FIR JS] Report WRONG_JS_QUALIFIER for the argument of JsQualifier
This commit is contained in:
committed by
Space Team
parent
73c89a5d9d
commit
f422a3a4e8
@@ -206,6 +206,7 @@
|
|||||||
/core/builtins/ "Kotlin Compiler Core"
|
/core/builtins/ "Kotlin Compiler Core"
|
||||||
/core/compiler.common/ "Kotlin Compiler Core"
|
/core/compiler.common/ "Kotlin Compiler Core"
|
||||||
/core/compiler.common.jvm/ "Kotlin Compiler Core"
|
/core/compiler.common.jvm/ "Kotlin Compiler Core"
|
||||||
|
/core/compiler.common.js/ "Kotlin Compiler Core"
|
||||||
/core/descriptors/ "Kotlin Compiler Core"
|
/core/descriptors/ "Kotlin Compiler Core"
|
||||||
/core/descriptors.jvm/ "Kotlin Compiler Core"
|
/core/descriptors.jvm/ "Kotlin Compiler Core"
|
||||||
/core/descriptors.runtime/ "Kotlin Libraries"
|
/core/descriptors.runtime/ "Kotlin Libraries"
|
||||||
|
|||||||
+2
-1
@@ -10,10 +10,11 @@ import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.JVM_DIAGNOSTICS_L
|
|||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
import org.jetbrains.kotlin.analysis.api.fir.generator.DiagnosticClassGenerator.generate
|
import org.jetbrains.kotlin.analysis.api.fir.generator.DiagnosticClassGenerator.generate
|
||||||
import org.jetbrains.kotlin.fir.builder.SYNTAX_DIAGNOSTIC_LIST
|
import org.jetbrains.kotlin.fir.builder.SYNTAX_DIAGNOSTIC_LIST
|
||||||
|
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.JS_DIAGNOSTICS_LIST
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
val rootPath = Paths.get("analysis/analysis-api-fir/src").toAbsolutePath()
|
val rootPath = Paths.get("analysis/analysis-api-fir/src").toAbsolutePath()
|
||||||
val packageName = "org.jetbrains.kotlin.analysis.api.fir.diagnostics"
|
val packageName = "org.jetbrains.kotlin.analysis.api.fir.diagnostics"
|
||||||
val diagnostics = DIAGNOSTICS_LIST + JVM_DIAGNOSTICS_LIST + SYNTAX_DIAGNOSTIC_LIST
|
val diagnostics = DIAGNOSTICS_LIST + JVM_DIAGNOSTICS_LIST + JS_DIAGNOSTICS_LIST + SYNTAX_DIAGNOSTIC_LIST
|
||||||
generate(rootPath, diagnostics, packageName)
|
generate(rootPath, diagnostics, packageName)
|
||||||
}
|
}
|
||||||
|
|||||||
+6
@@ -976,6 +976,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
|||||||
token,
|
token,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
add(FirJsErrors.WRONG_JS_QUALIFIER) { firDiagnostic ->
|
||||||
|
WrongJsQualifierImpl(
|
||||||
|
firDiagnostic as KtPsiDiagnostic,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
add(FirErrors.OPT_IN_USAGE) { firDiagnostic ->
|
add(FirErrors.OPT_IN_USAGE) { firDiagnostic ->
|
||||||
OptInUsageImpl(
|
OptInUsageImpl(
|
||||||
firDiagnostic.a,
|
firDiagnostic.a,
|
||||||
|
|||||||
+4
@@ -703,6 +703,10 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
|||||||
abstract val typeFromTypesPhase: KtType
|
abstract val typeFromTypesPhase: KtType
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract class WrongJsQualifier : KtFirDiagnostic<KtElement>() {
|
||||||
|
override val diagnosticClass get() = WrongJsQualifier::class
|
||||||
|
}
|
||||||
|
|
||||||
abstract class OptInUsage : KtFirDiagnostic<PsiElement>() {
|
abstract class OptInUsage : KtFirDiagnostic<PsiElement>() {
|
||||||
override val diagnosticClass get() = OptInUsage::class
|
override val diagnosticClass get() = OptInUsage::class
|
||||||
abstract val optInMarkerFqName: FqName
|
abstract val optInMarkerFqName: FqName
|
||||||
|
|||||||
+5
@@ -844,6 +844,11 @@ internal class PluginAnnotationAmbiguityImpl(
|
|||||||
override val token: KtLifetimeToken,
|
override val token: KtLifetimeToken,
|
||||||
) : KtFirDiagnostic.PluginAnnotationAmbiguity(), KtAbstractFirDiagnostic<PsiElement>
|
) : KtFirDiagnostic.PluginAnnotationAmbiguity(), KtAbstractFirDiagnostic<PsiElement>
|
||||||
|
|
||||||
|
internal class WrongJsQualifierImpl(
|
||||||
|
override val firDiagnostic: KtPsiDiagnostic,
|
||||||
|
override val token: KtLifetimeToken,
|
||||||
|
) : KtFirDiagnostic.WrongJsQualifier(), KtAbstractFirDiagnostic<KtElement>
|
||||||
|
|
||||||
internal class OptInUsageImpl(
|
internal class OptInUsageImpl(
|
||||||
override val optInMarkerFqName: FqName,
|
override val optInMarkerFqName: FqName,
|
||||||
override val message: String,
|
override val message: String,
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ dependencies {
|
|||||||
compileOnly(project(":compiler:psi"))
|
compileOnly(project(":compiler:psi"))
|
||||||
compileOnly(project(":core:compiler.common"))
|
compileOnly(project(":core:compiler.common"))
|
||||||
compileOnly(project(":core:compiler.common.jvm"))
|
compileOnly(project(":core:compiler.common.jvm"))
|
||||||
|
compileOnly(project(":core:compiler.common.js"))
|
||||||
implementation(project(":analysis:analysis-internal-utils"))
|
implementation(project(":analysis:analysis-internal-utils"))
|
||||||
implementation(project(":analysis:analysis-api-providers"))
|
implementation(project(":analysis:analysis-api-providers"))
|
||||||
implementation(project(":analysis:kt-references"))
|
implementation(project(":analysis:kt-references"))
|
||||||
|
|||||||
@@ -142,6 +142,7 @@ val commonCompilerModules = arrayOf(
|
|||||||
":core:deserialization.common.jvm",
|
":core:deserialization.common.jvm",
|
||||||
":core:compiler.common",
|
":core:compiler.common",
|
||||||
":core:compiler.common.jvm",
|
":core:compiler.common.jvm",
|
||||||
|
":core:compiler.common.js",
|
||||||
":core:util.runtime",
|
":core:util.runtime",
|
||||||
":compiler:frontend.common.jvm",
|
":compiler:frontend.common.jvm",
|
||||||
":compiler:frontend.java", // TODO this is fe10 module but some utils used in fir ide now
|
":compiler:frontend.java", // TODO this is fe10 module but some utils used in fir ide now
|
||||||
@@ -237,6 +238,7 @@ extra["kotlinJpsPluginEmbeddedDependencies"] = listOf(
|
|||||||
":daemon-common",
|
":daemon-common",
|
||||||
":core:compiler.common",
|
":core:compiler.common",
|
||||||
":core:compiler.common.jvm",
|
":core:compiler.common.jvm",
|
||||||
|
":core:compiler.common.js",
|
||||||
":core:descriptors",
|
":core:descriptors",
|
||||||
":core:descriptors.jvm",
|
":core:descriptors.jvm",
|
||||||
":compiler:backend.common.jvm",
|
":compiler:backend.common.jvm",
|
||||||
|
|||||||
+6
-1
@@ -7,7 +7,12 @@ package org.jetbrains.kotlin.fir.checkers.generator.diagnostics
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.fir.PrivateForInline
|
import org.jetbrains.kotlin.fir.PrivateForInline
|
||||||
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.DiagnosticList
|
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.DiagnosticList
|
||||||
|
import org.jetbrains.kotlin.psi.KtElement
|
||||||
|
|
||||||
@Suppress("UNUSED_VARIABLE", "LocalVariableName", "ClassName", "unused")
|
@Suppress("UNUSED_VARIABLE", "LocalVariableName", "ClassName", "unused")
|
||||||
@OptIn(PrivateForInline::class)
|
@OptIn(PrivateForInline::class)
|
||||||
object JS_DIAGNOSTICS_LIST : DiagnosticList("FirJsErrors")
|
object JS_DIAGNOSTICS_LIST : DiagnosticList("FirJsErrors") {
|
||||||
|
val ANNOTATIONS by object : DiagnosticGroup("Annotations") {
|
||||||
|
val WRONG_JS_QUALIFIER by error<KtElement>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
api(project(":core:compiler.common.js"))
|
||||||
api(project(":compiler:fir:checkers"))
|
api(project(":compiler:fir:checkers"))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
+4
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.analysis.diagnostics.js
|
|||||||
import org.jetbrains.kotlin.diagnostics.*
|
import org.jetbrains.kotlin.diagnostics.*
|
||||||
import org.jetbrains.kotlin.diagnostics.rendering.RootDiagnosticRendererFactory
|
import org.jetbrains.kotlin.diagnostics.rendering.RootDiagnosticRendererFactory
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.*
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.*
|
||||||
|
import org.jetbrains.kotlin.psi.KtElement
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This file was generated automatically
|
* This file was generated automatically
|
||||||
@@ -15,6 +16,9 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.*
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
object FirJsErrors {
|
object FirJsErrors {
|
||||||
|
// Annotations
|
||||||
|
val WRONG_JS_QUALIFIER by error0<KtElement>()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
RootDiagnosticRendererFactory.registerFactory(FirJsErrorsDefaultMessages)
|
RootDiagnosticRendererFactory.registerFactory(FirJsErrorsDefaultMessages)
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-1
@@ -7,9 +7,14 @@ package org.jetbrains.kotlin.fir.analysis.diagnostics.js
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactoryToRendererMap
|
import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactoryToRendererMap
|
||||||
import org.jetbrains.kotlin.diagnostics.rendering.BaseDiagnosticRendererFactory
|
import org.jetbrains.kotlin.diagnostics.rendering.BaseDiagnosticRendererFactory
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.checkMissingMessages
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.WRONG_JS_QUALIFIER
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
object FirJsErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
|
object FirJsErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
|
||||||
override val MAP = KtDiagnosticFactoryToRendererMap("FIR").also { _ ->
|
override val MAP = KtDiagnosticFactoryToRendererMap("FIR").also { map ->
|
||||||
|
map.put(WRONG_JS_QUALIFIER, "Qualifier contains illegal characters")
|
||||||
|
|
||||||
|
map.checkMissingMessages(FirJsErrors)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+7
-1
@@ -6,5 +6,11 @@
|
|||||||
package org.jetbrains.kotlin.fir.analysis.js.checkers
|
package org.jetbrains.kotlin.fir.analysis.js.checkers
|
||||||
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.expression.*
|
import org.jetbrains.kotlin.fir.analysis.checkers.expression.*
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.js.checkers.expression.FirJsQualifierChecker
|
||||||
|
|
||||||
object JsExpressionCheckers : ExpressionCheckers()
|
object JsExpressionCheckers : ExpressionCheckers() {
|
||||||
|
override val annotationCallCheckers: Set<FirAnnotationCallChecker>
|
||||||
|
get() = setOf(
|
||||||
|
FirJsQualifierChecker,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
+33
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* 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.expression
|
||||||
|
|
||||||
|
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.expression.FirAnnotationCallChecker
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.fullyExpandedClassId
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
|
||||||
|
import org.jetbrains.kotlin.js.validateQualifier
|
||||||
|
import org.jetbrains.kotlin.name.JsStandardClassIds.Annotations.JsQualifier
|
||||||
|
|
||||||
|
object FirJsQualifierChecker : FirAnnotationCallChecker() {
|
||||||
|
override fun check(expression: FirAnnotationCall, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
val annotationFqName = expression.fullyExpandedClassId(context.session)
|
||||||
|
|
||||||
|
if (annotationFqName != JsQualifier) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val string = (expression.argumentMapping.mapping.values.firstOrNull() as? FirConstExpression<*>)?.value as? String ?: return
|
||||||
|
|
||||||
|
if (!validateQualifier(string)) {
|
||||||
|
reporter.reportOn(expression.argumentList.arguments.first().source, FirJsErrors.WRONG_JS_QUALIFIER, context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
-17
@@ -1,17 +0,0 @@
|
|||||||
// FILE: a.kt
|
|
||||||
@file:JsQualifier("")
|
|
||||||
|
|
||||||
// FILE: b.kt
|
|
||||||
@file:JsQualifier("a..b")
|
|
||||||
|
|
||||||
// FILE: c.kt
|
|
||||||
@file:JsQualifier("a.")
|
|
||||||
|
|
||||||
// FILE: d.kt
|
|
||||||
@file:JsQualifier(".a")
|
|
||||||
|
|
||||||
// FILE: e.kt
|
|
||||||
@file:JsQualifier("%^&")
|
|
||||||
|
|
||||||
// FILE: f.kt
|
|
||||||
@file:JsQualifier("a.bc.d23._$")
|
|
||||||
+8
-1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// FILE: a.kt
|
// FILE: a.kt
|
||||||
@file:JsQualifier(<!WRONG_JS_QUALIFIER!>""<!>)
|
@file:JsQualifier(<!WRONG_JS_QUALIFIER!>""<!>)
|
||||||
|
|
||||||
@@ -14,4 +15,10 @@
|
|||||||
@file:JsQualifier(<!WRONG_JS_QUALIFIER!>"%^&"<!>)
|
@file:JsQualifier(<!WRONG_JS_QUALIFIER!>"%^&"<!>)
|
||||||
|
|
||||||
// FILE: f.kt
|
// FILE: f.kt
|
||||||
@file:JsQualifier("a.bc.d23._$")
|
@file:JsQualifier("a.bc.d23._$")
|
||||||
|
|
||||||
|
// FILE: g.kt
|
||||||
|
typealias JsQ = JsQualifier
|
||||||
|
|
||||||
|
// FILE: h.kt
|
||||||
|
@file:JsQ(<!WRONG_JS_QUALIFIER!>value = "%^&"<!>)
|
||||||
|
|||||||
@@ -1 +1,4 @@
|
|||||||
package
|
package
|
||||||
|
|
||||||
|
public typealias JsQ = kotlin.js.JsQualifier
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
plugins {
|
||||||
|
kotlin("jvm")
|
||||||
|
id("jps-compatible")
|
||||||
|
}
|
||||||
|
|
||||||
|
project.configureJvmToolchain(JdkMajorVersion.JDK_1_8)
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
api(project(":core:compiler.common"))
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
"main" { projectDefault() }
|
||||||
|
"test" {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* 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.js
|
||||||
|
|
||||||
|
fun validateQualifier(qualifier: String): Boolean {
|
||||||
|
val parts = qualifier.split('.')
|
||||||
|
if (parts.isEmpty()) return false
|
||||||
|
|
||||||
|
return parts.all { part ->
|
||||||
|
part.isNotEmpty() && part[0].isJavaIdentifierStart() && part.drop(1).all(Char::isJavaIdentifierPart)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* 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.name
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.name.StandardClassIds.BASE_KOTLIN_PACKAGE
|
||||||
|
|
||||||
|
object JsStandardClassIds {
|
||||||
|
val BASE_JS_PACKAGE = BASE_KOTLIN_PACKAGE.child(Name.identifier("js"))
|
||||||
|
|
||||||
|
object Annotations {
|
||||||
|
val JsQualifier = "JsQualifier".jsId()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun String.jsId() = ClassId(JsStandardClassIds.BASE_JS_PACKAGE, Name.identifier(this))
|
||||||
+1
-9
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.js.resolve.diagnostics
|
|||||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
|
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
|
||||||
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
|
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
|
||||||
|
import org.jetbrains.kotlin.js.validateQualifier
|
||||||
import org.jetbrains.kotlin.psi.KtAnnotated
|
import org.jetbrains.kotlin.psi.KtAnnotated
|
||||||
import org.jetbrains.kotlin.psi.KtAnnotationEntry
|
import org.jetbrains.kotlin.psi.KtAnnotationEntry
|
||||||
import org.jetbrains.kotlin.resolve.AdditionalAnnotationChecker
|
import org.jetbrains.kotlin.resolve.AdditionalAnnotationChecker
|
||||||
@@ -44,13 +45,4 @@ object JsQualifierChecker : AdditionalAnnotationChecker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun validateQualifier(qualifier: String): Boolean {
|
|
||||||
val parts = qualifier.split('.')
|
|
||||||
if (parts.isEmpty()) return false
|
|
||||||
|
|
||||||
return parts.all { part ->
|
|
||||||
part.isNotEmpty() && part[0].isJavaIdentifierStart() && part.drop(1).all(Char::isJavaIdentifierPart)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -152,6 +152,7 @@ include ":benchmarks",
|
|||||||
":native:kotlin-klib-commonizer-embeddable",
|
":native:kotlin-klib-commonizer-embeddable",
|
||||||
":core:compiler.common",
|
":core:compiler.common",
|
||||||
":core:compiler.common.jvm",
|
":core:compiler.common.jvm",
|
||||||
|
":core:compiler.common.js",
|
||||||
":compiler:backend.common.jvm",
|
":compiler:backend.common.jvm",
|
||||||
":core:descriptors",
|
":core:descriptors",
|
||||||
":core:descriptors.jvm",
|
":core:descriptors.jvm",
|
||||||
|
|||||||
Reference in New Issue
Block a user