[FIR JS] Report WRONG_JS_QUALIFIER for the argument of JsQualifier

This commit is contained in:
Nikolay Lunyak
2023-01-03 13:38:57 +02:00
committed by Space Team
parent 73c89a5d9d
commit f422a3a4e8
21 changed files with 139 additions and 31 deletions
+1
View File
@@ -206,6 +206,7 @@
/core/builtins/ "Kotlin Compiler Core"
/core/compiler.common/ "Kotlin Compiler Core"
/core/compiler.common.jvm/ "Kotlin Compiler Core"
/core/compiler.common.js/ "Kotlin Compiler Core"
/core/descriptors/ "Kotlin Compiler Core"
/core/descriptors.jvm/ "Kotlin Compiler Core"
/core/descriptors.runtime/ "Kotlin Libraries"
@@ -10,10 +10,11 @@ import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.JVM_DIAGNOSTICS_L
import java.nio.file.Paths
import org.jetbrains.kotlin.analysis.api.fir.generator.DiagnosticClassGenerator.generate
import org.jetbrains.kotlin.fir.builder.SYNTAX_DIAGNOSTIC_LIST
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.JS_DIAGNOSTICS_LIST
fun main() {
val rootPath = Paths.get("analysis/analysis-api-fir/src").toAbsolutePath()
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)
}
@@ -976,6 +976,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token,
)
}
add(FirJsErrors.WRONG_JS_QUALIFIER) { firDiagnostic ->
WrongJsQualifierImpl(
firDiagnostic as KtPsiDiagnostic,
token,
)
}
add(FirErrors.OPT_IN_USAGE) { firDiagnostic ->
OptInUsageImpl(
firDiagnostic.a,
@@ -703,6 +703,10 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
abstract val typeFromTypesPhase: KtType
}
abstract class WrongJsQualifier : KtFirDiagnostic<KtElement>() {
override val diagnosticClass get() = WrongJsQualifier::class
}
abstract class OptInUsage : KtFirDiagnostic<PsiElement>() {
override val diagnosticClass get() = OptInUsage::class
abstract val optInMarkerFqName: FqName
@@ -844,6 +844,11 @@ internal class PluginAnnotationAmbiguityImpl(
override val token: KtLifetimeToken,
) : KtFirDiagnostic.PluginAnnotationAmbiguity(), KtAbstractFirDiagnostic<PsiElement>
internal class WrongJsQualifierImpl(
override val firDiagnostic: KtPsiDiagnostic,
override val token: KtLifetimeToken,
) : KtFirDiagnostic.WrongJsQualifier(), KtAbstractFirDiagnostic<KtElement>
internal class OptInUsageImpl(
override val optInMarkerFqName: FqName,
override val message: String,
+1
View File
@@ -14,6 +14,7 @@ dependencies {
compileOnly(project(":compiler:psi"))
compileOnly(project(":core:compiler.common"))
compileOnly(project(":core:compiler.common.jvm"))
compileOnly(project(":core:compiler.common.js"))
implementation(project(":analysis:analysis-internal-utils"))
implementation(project(":analysis:analysis-api-providers"))
implementation(project(":analysis:kt-references"))
+2
View File
@@ -142,6 +142,7 @@ val commonCompilerModules = arrayOf(
":core:deserialization.common.jvm",
":core:compiler.common",
":core:compiler.common.jvm",
":core:compiler.common.js",
":core:util.runtime",
":compiler:frontend.common.jvm",
":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",
":core:compiler.common",
":core:compiler.common.jvm",
":core:compiler.common.js",
":core:descriptors",
":core:descriptors.jvm",
":compiler:backend.common.jvm",
@@ -7,7 +7,12 @@ package org.jetbrains.kotlin.fir.checkers.generator.diagnostics
import org.jetbrains.kotlin.fir.PrivateForInline
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.DiagnosticList
import org.jetbrains.kotlin.psi.KtElement
@Suppress("UNUSED_VARIABLE", "LocalVariableName", "ClassName", "unused")
@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 {
api(project(":core:compiler.common.js"))
api(project(":compiler:fir:checkers"))
/*
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.analysis.diagnostics.js
import org.jetbrains.kotlin.diagnostics.*
import org.jetbrains.kotlin.diagnostics.rendering.RootDiagnosticRendererFactory
import org.jetbrains.kotlin.fir.analysis.diagnostics.*
import org.jetbrains.kotlin.psi.KtElement
/*
* This file was generated automatically
@@ -15,6 +16,9 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.*
*/
object FirJsErrors {
// Annotations
val WRONG_JS_QUALIFIER by error0<KtElement>()
init {
RootDiagnosticRendererFactory.registerFactory(FirJsErrorsDefaultMessages)
}
@@ -7,9 +7,14 @@ package org.jetbrains.kotlin.fir.analysis.diagnostics.js
import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactoryToRendererMap
import org.jetbrains.kotlin.diagnostics.rendering.BaseDiagnosticRendererFactory
import org.jetbrains.kotlin.fir.analysis.diagnostics.checkMissingMessages
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.WRONG_JS_QUALIFIER
@Suppress("unused")
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)
}
}
@@ -6,5 +6,11 @@
package org.jetbrains.kotlin.fir.analysis.js.checkers
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,
)
}
@@ -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)
}
}
}
@@ -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._$")
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// FILE: a.kt
@file:JsQualifier(<!WRONG_JS_QUALIFIER!>""<!>)
@@ -14,4 +15,10 @@
@file:JsQualifier(<!WRONG_JS_QUALIFIER!>"%^&"<!>)
// 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
public typealias JsQ = kotlin.js.JsQualifier
+15
View File
@@ -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))
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.js.resolve.diagnostics
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
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.KtAnnotationEntry
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)
}
}
}
+1
View File
@@ -152,6 +152,7 @@ include ":benchmarks",
":native:kotlin-klib-commonizer-embeddable",
":core:compiler.common",
":core:compiler.common.jvm",
":core:compiler.common.js",
":compiler:backend.common.jvm",
":core:descriptors",
":core:descriptors.jvm",