[FIR] KT-46483: Forbid annotations in where Clauses

Merge-request: KT-MR-7208
Merged-by: Nikolay Lunyak <lunyak.kolya@mail.ru>
This commit is contained in:
Nikolay Lunyak
2022-09-28 13:38:18 +00:00
committed by Space
parent a20ce06102
commit f578381726
37 changed files with 462 additions and 20 deletions
@@ -955,6 +955,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token,
)
}
add(FirErrors.ANNOTATION_IN_WHERE_CLAUSE_ERROR) { firDiagnostic ->
AnnotationInWhereClauseErrorImpl(
firDiagnostic as KtPsiDiagnostic,
token,
)
}
add(FirErrors.OPT_IN_USAGE) { firDiagnostic ->
OptInUsageImpl(
firDiagnostic.a,
@@ -689,6 +689,10 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
override val diagnosticClass get() = WrongExtensionFunctionTypeWarning::class
}
abstract class AnnotationInWhereClauseError : KtFirDiagnostic<KtAnnotationEntry>() {
override val diagnosticClass get() = AnnotationInWhereClauseError::class
}
abstract class OptInUsage : KtFirDiagnostic<PsiElement>() {
override val diagnosticClass get() = OptInUsage::class
abstract val optInMarkerFqName: FqName
@@ -827,6 +827,11 @@ internal class WrongExtensionFunctionTypeWarningImpl(
override val token: KtLifetimeToken,
) : KtFirDiagnostic.WrongExtensionFunctionTypeWarning(), KtAbstractFirDiagnostic<KtAnnotationEntry>
internal class AnnotationInWhereClauseErrorImpl(
override val firDiagnostic: KtPsiDiagnostic,
override val token: KtLifetimeToken,
) : KtFirDiagnostic.AnnotationInWhereClauseError(), KtAbstractFirDiagnostic<KtAnnotationEntry>
internal class OptInUsageImpl(
override val optInMarkerFqName: FqName,
override val message: String,
@@ -423,6 +423,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
runTest("compiler/testData/diagnostics/tests/kt435.kt");
}
@Test
@TestMetadata("kt46483.kt")
public void testKt46483() throws Exception {
runTest("compiler/testData/diagnostics/tests/kt46483.kt");
}
@Test
@TestMetadata("kt49438.kt")
public void testKt49438() throws Exception {
@@ -423,6 +423,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/tests/kt435.kt");
}
@Test
@TestMetadata("kt46483.kt")
public void testKt46483() throws Exception {
runTest("compiler/testData/diagnostics/tests/kt46483.kt");
}
@Test
@TestMetadata("kt49438.kt")
public void testKt49438() throws Exception {
@@ -423,6 +423,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
runTest("compiler/testData/diagnostics/tests/kt435.kt");
}
@Test
@TestMetadata("kt46483.kt")
public void testKt46483() throws Exception {
runTest("compiler/testData/diagnostics/tests/kt46483.kt");
}
@Test
@TestMetadata("kt49438.kt")
public void testKt49438() throws Exception {
@@ -291,6 +291,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
val NOT_A_CLASS by error<PsiElement>()
val WRONG_EXTENSION_FUNCTION_TYPE by error<KtAnnotationEntry>()
val WRONG_EXTENSION_FUNCTION_TYPE_WARNING by warning<KtAnnotationEntry>()
val ANNOTATION_IN_WHERE_CLAUSE_ERROR by error<KtAnnotationEntry>()
}
val OPT_IN by object : DiagnosticGroup("OptIn") {
@@ -256,6 +256,7 @@ object FirErrors {
val NOT_A_CLASS by error0<PsiElement>()
val WRONG_EXTENSION_FUNCTION_TYPE by error0<KtAnnotationEntry>()
val WRONG_EXTENSION_FUNCTION_TYPE_WARNING by warning0<KtAnnotationEntry>()
val ANNOTATION_IN_WHERE_CLAUSE_ERROR by error0<KtAnnotationEntry>()
// OptIn
val OPT_IN_USAGE by warning2<PsiElement, FqName, String>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
@@ -46,6 +46,11 @@ class ErrorNodeDiagnosticCollectorComponent(
}
}
override fun visitErrorAnnotationCall(errorAnnotationCall: FirErrorAnnotationCall, data: CheckerContext) {
val source = errorAnnotationCall.source ?: return
reportFirDiagnostic(errorAnnotationCall.diagnostic, source, data)
}
override fun visitErrorNamedReference(errorNamedReference: FirErrorNamedReference, data: CheckerContext) {
val source = errorNamedReference.source ?: return
val qualifiedAccessOrAnnotationCall = data.qualifiedAccessOrAnnotationCalls.lastOrNull()?.takeIf {
@@ -67,6 +67,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ANNOTATION_ARGUME
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ANNOTATION_ARGUMENT_MUST_BE_KCLASS_LITERAL
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ANNOTATION_CLASS_CONSTRUCTOR_CALL
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ANNOTATION_CLASS_MEMBER
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ANNOTATION_IN_WHERE_CLAUSE_ERROR
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ANNOTATION_ON_SUPERCLASS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ANNOTATION_PARAMETER_DEFAULT_VALUE_MUST_BE_CONSTANT
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ANNOTATION_USED_AS_ANNOTATION_ARGUMENT
@@ -887,6 +888,10 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
WRONG_EXTENSION_FUNCTION_TYPE_WARNING,
"ExtensionFunctionType makes no sense on a non-function type. It will be an error in a future release. See https://youtrack.jetbrains.com/issue/KT-43527"
)
map.put(
ANNOTATION_IN_WHERE_CLAUSE_ERROR,
"Type parameter annotations are not allowed inside where clauses. You should probably move annotations to the type parameter declaration",
)
// Exposed visibility group // #
map.put(
@@ -512,6 +512,7 @@ private fun ConeSimpleDiagnostic.getFactory(source: KtSourceElement): KtDiagnost
DiagnosticKind.EnumEntryAsType -> FirErrors.ENUM_ENTRY_AS_TYPE
DiagnosticKind.NotASupertype -> FirErrors.NOT_A_SUPERTYPE
DiagnosticKind.SuperNotAvailable -> FirErrors.SUPER_NOT_AVAILABLE
DiagnosticKind.AnnotationNotAllowed -> FirErrors.ANNOTATION_IN_WHERE_CLAUSE_ERROR
DiagnosticKind.UnresolvedSupertype,
DiagnosticKind.UnresolvedExpandedType,
DiagnosticKind.Other -> FirErrors.OTHER_ERROR
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.*
import org.jetbrains.kotlin.ElementTypeUtils.isExpression
import org.jetbrains.kotlin.KtNodeTypes.*
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
@@ -29,6 +30,7 @@ import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.builder.*
import org.jetbrains.kotlin.fir.declarations.impl.*
import org.jetbrains.kotlin.fir.declarations.utils.*
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
import org.jetbrains.kotlin.fir.expressions.*
@@ -367,7 +369,8 @@ class DeclarationsConverter(
*/
fun convertAnnotationEntry(
unescapedAnnotation: LighterASTNode,
defaultAnnotationUseSiteTarget: AnnotationUseSiteTarget? = null
defaultAnnotationUseSiteTarget: AnnotationUseSiteTarget? = null,
diagnostic: ConeDiagnostic? = null,
): FirAnnotationCall {
var annotationUseSiteTarget: AnnotationUseSiteTarget? = null
lateinit var constructorCalleePair: Pair<FirTypeRef, List<FirExpression>>
@@ -379,21 +382,34 @@ class DeclarationsConverter(
}
val qualifier = (constructorCalleePair.first as? FirUserTypeRef)?.qualifier?.last()
val name = qualifier?.name ?: Name.special("<no-annotation-name>")
return buildAnnotationCall {
source = unescapedAnnotation.toFirSourceElement()
useSiteTarget = annotationUseSiteTarget ?: defaultAnnotationUseSiteTarget
annotationTypeRef = constructorCalleePair.first
calleeReference = buildSimpleNamedReference {
source = unescapedAnnotation
.getChildNodeByType(CONSTRUCTOR_CALLEE)
?.getChildNodeByType(TYPE_REFERENCE)
?.getChildNodeByType(USER_TYPE)
?.getChildNodeByType(REFERENCE_EXPRESSION)
?.toFirSourceElement()
this.name = name
val theCalleeReference = buildSimpleNamedReference {
source = unescapedAnnotation
.getChildNodeByType(CONSTRUCTOR_CALLEE)
?.getChildNodeByType(TYPE_REFERENCE)
?.getChildNodeByType(USER_TYPE)
?.getChildNodeByType(REFERENCE_EXPRESSION)
?.toFirSourceElement()
this.name = name
}
return if (diagnostic == null) {
buildAnnotationCall {
source = unescapedAnnotation.toFirSourceElement()
useSiteTarget = annotationUseSiteTarget ?: defaultAnnotationUseSiteTarget
annotationTypeRef = constructorCalleePair.first
calleeReference = theCalleeReference
extractArgumentsFrom(constructorCalleePair.second)
typeArguments += qualifier?.typeArgumentList?.typeArguments ?: listOf()
}
} else {
buildErrorAnnotationCall {
source = unescapedAnnotation.toFirSourceElement()
useSiteTarget = annotationUseSiteTarget ?: defaultAnnotationUseSiteTarget
annotationTypeRef = constructorCalleePair.first
this.diagnostic = diagnostic
calleeReference = theCalleeReference
extractArgumentsFrom(constructorCalleePair.second)
typeArguments += qualifier?.typeArgumentList?.typeArguments ?: listOf()
}
extractArgumentsFrom(constructorCalleePair.second)
typeArguments += qualifier?.typeArgumentList?.typeArguments ?: listOf()
}
}
@@ -1875,11 +1891,15 @@ class DeclarationsConverter(
lateinit var identifier: String
lateinit var firType: FirTypeRef
lateinit var referenceExpression: LighterASTNode
val diagnostic = ConeSimpleDiagnostic(
"Type parameter annotations are not allowed inside where clauses", DiagnosticKind.AnnotationNotAllowed,
)
val annotations = mutableListOf<FirAnnotation>()
typeConstraint.forEachChildren {
when (it.tokenType) {
//annotations will be saved later, on mapping stage with type parameters
ANNOTATION, ANNOTATION_ENTRY -> annotations += convertAnnotation(it)
ANNOTATION_ENTRY -> annotations += convertAnnotationEntry(it, diagnostic = diagnostic)
REFERENCE_EXPRESSION -> {
identifier = it.asText
referenceExpression = it
@@ -9,6 +9,7 @@ import com.intellij.psi.PsiElement
import com.intellij.psi.tree.IElementType
import org.jetbrains.kotlin.*
import org.jetbrains.kotlin.builtins.StandardNames.BACKING_FIELD
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
@@ -702,9 +703,29 @@ open class RawFirBuilder(
val owner = parameter.getStrictParentOfType<KtTypeParameterListOwner>() ?: return@buildTypeParameter
for (typeConstraint in owner.typeConstraints) {
val subjectName = typeConstraint.subjectTypeParameterName?.getReferencedNameAsName()
if (subjectName == parameterName) {
bounds += typeConstraint.boundTypeReference.toFirOrErrorType()
}
for (entry in typeConstraint.annotationEntries) {
annotations += buildErrorAnnotationCall {
source = entry.toFirSourceElement()
useSiteTarget = entry.useSiteTarget?.getAnnotationUseSiteTarget()
annotationTypeRef = entry.typeReference.toFirOrErrorType()
diagnostic = ConeSimpleDiagnostic(
"Type parameter annotations are not allowed inside where clauses", DiagnosticKind.AnnotationNotAllowed,
)
val name = (annotationTypeRef as? FirUserTypeRef)?.qualifier?.last()?.name
?: Name.special("<no-annotation-name>")
calleeReference = buildSimpleNamedReference {
source = (entry.typeReference?.typeElement as? KtUserType)?.referenceExpression?.toFirSourceElement()
this.name = name
}
entry.extractArgumentsTo(this)
typeArguments.appendTypeArguments(entry.typeArguments)
}
}
}
addDefaultBoundIfNecessary()
}
@@ -219,6 +219,10 @@ open class FirBodyResolveTransformer(
return expressionsTransformer.transformAnnotationCall(annotationCall, data)
}
override fun transformErrorAnnotationCall(errorAnnotationCall: FirErrorAnnotationCall, data: ResolutionMode): FirStatement {
return transformAnnotationCall(errorAnnotationCall, data)
}
override fun transformDelegatedConstructorCall(
delegatedConstructorCall: FirDelegatedConstructorCall,
data: ResolutionMode
@@ -0,0 +1,58 @@
/*
* Copyright 2010-2022 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.expressions
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.FirDiagnosticHolder
import org.jetbrains.kotlin.fir.references.FirReference
import org.jetbrains.kotlin.fir.types.FirTypeProjection
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.visitors.*
/*
* This file was generated automatically
* DO NOT MODIFY IT MANUALLY
*/
abstract class FirErrorAnnotationCall : FirAnnotationCall(), FirDiagnosticHolder {
abstract override val source: KtSourceElement?
abstract override val typeRef: FirTypeRef
abstract override val annotations: List<FirAnnotation>
abstract override val useSiteTarget: AnnotationUseSiteTarget?
abstract override val annotationTypeRef: FirTypeRef
abstract override val typeArguments: List<FirTypeProjection>
abstract override val argumentList: FirArgumentList
abstract override val calleeReference: FirReference
abstract override val diagnostic: ConeDiagnostic
abstract override val argumentMapping: FirAnnotationArgumentMapping
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitErrorAnnotationCall(this, data)
@Suppress("UNCHECKED_CAST")
override fun <E: FirElement, D> transform(transformer: FirTransformer<D>, data: D): E =
transformer.transformErrorAnnotationCall(this, data) as E
abstract override fun replaceTypeRef(newTypeRef: FirTypeRef)
abstract override fun replaceTypeArguments(newTypeArguments: List<FirTypeProjection>)
abstract override fun replaceArgumentList(newArgumentList: FirArgumentList)
abstract override fun replaceCalleeReference(newCalleeReference: FirReference)
abstract override fun replaceArgumentMapping(newArgumentMapping: FirAnnotationArgumentMapping)
abstract override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirErrorAnnotationCall
abstract override fun <D> transformAnnotationTypeRef(transformer: FirTransformer<D>, data: D): FirErrorAnnotationCall
abstract override fun <D> transformTypeArguments(transformer: FirTransformer<D>, data: D): FirErrorAnnotationCall
abstract override fun <D> transformCalleeReference(transformer: FirTransformer<D>, data: D): FirErrorAnnotationCall
}
@@ -0,0 +1,78 @@
/*
* Copyright 2010-2022 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.
*/
@file:Suppress("DuplicatedCode")
package org.jetbrains.kotlin.fir.expressions.builder
import kotlin.contracts.*
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.fir.builder.FirAnnotationContainerBuilder
import org.jetbrains.kotlin.fir.builder.FirBuilderDsl
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.FirAnnotationArgumentMapping
import org.jetbrains.kotlin.fir.expressions.FirArgumentList
import org.jetbrains.kotlin.fir.expressions.FirEmptyArgumentList
import org.jetbrains.kotlin.fir.expressions.FirErrorAnnotationCall
import org.jetbrains.kotlin.fir.expressions.builder.FirCallBuilder
import org.jetbrains.kotlin.fir.expressions.builder.FirExpressionBuilder
import org.jetbrains.kotlin.fir.expressions.impl.FirEmptyAnnotationArgumentMapping
import org.jetbrains.kotlin.fir.expressions.impl.FirErrorAnnotationCallImpl
import org.jetbrains.kotlin.fir.references.FirReference
import org.jetbrains.kotlin.fir.types.FirTypeProjection
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.impl.FirImplicitTypeRefImpl
import org.jetbrains.kotlin.fir.visitors.*
/*
* This file was generated automatically
* DO NOT MODIFY IT MANUALLY
*/
@FirBuilderDsl
class FirErrorAnnotationCallBuilder : FirCallBuilder, FirAnnotationContainerBuilder, FirExpressionBuilder {
override var source: KtSourceElement? = null
var useSiteTarget: AnnotationUseSiteTarget? = null
var annotationTypeRef: FirTypeRef = FirImplicitTypeRefImpl(null)
val typeArguments: MutableList<FirTypeProjection> = mutableListOf()
override var argumentList: FirArgumentList = FirEmptyArgumentList
lateinit var calleeReference: FirReference
lateinit var diagnostic: ConeDiagnostic
var argumentMapping: FirAnnotationArgumentMapping = FirEmptyAnnotationArgumentMapping
override fun build(): FirErrorAnnotationCall {
return FirErrorAnnotationCallImpl(
source,
useSiteTarget,
annotationTypeRef,
typeArguments,
argumentList,
calleeReference,
diagnostic,
argumentMapping,
)
}
@Deprecated("Modification of 'typeRef' has no impact for FirErrorAnnotationCallBuilder", level = DeprecationLevel.HIDDEN)
override var typeRef: FirTypeRef
get() = throw IllegalStateException()
set(_) {
throw IllegalStateException()
}
@Deprecated("Modification of 'annotations' has no impact for FirErrorAnnotationCallBuilder", level = DeprecationLevel.HIDDEN)
override val annotations: MutableList<FirAnnotation> = mutableListOf()
}
@OptIn(ExperimentalContracts::class)
inline fun buildErrorAnnotationCall(init: FirErrorAnnotationCallBuilder.() -> Unit): FirErrorAnnotationCall {
contract {
callsInPlace(init, kotlin.contracts.InvocationKind.EXACTLY_ONCE)
}
return FirErrorAnnotationCallBuilder().apply(init).build()
}
@@ -0,0 +1,92 @@
/*
* Copyright 2010-2022 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.
*/
@file:Suppress("DuplicatedCode")
package org.jetbrains.kotlin.fir.expressions.impl
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.FirAnnotationArgumentMapping
import org.jetbrains.kotlin.fir.expressions.FirArgumentList
import org.jetbrains.kotlin.fir.expressions.FirErrorAnnotationCall
import org.jetbrains.kotlin.fir.references.FirReference
import org.jetbrains.kotlin.fir.types.FirTypeProjection
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.visitors.*
/*
* This file was generated automatically
* DO NOT MODIFY IT MANUALLY
*/
internal class FirErrorAnnotationCallImpl(
override val source: KtSourceElement?,
override val useSiteTarget: AnnotationUseSiteTarget?,
override var annotationTypeRef: FirTypeRef,
override val typeArguments: MutableList<FirTypeProjection>,
override var argumentList: FirArgumentList,
override var calleeReference: FirReference,
override val diagnostic: ConeDiagnostic,
override var argumentMapping: FirAnnotationArgumentMapping,
) : FirErrorAnnotationCall() {
override val typeRef: FirTypeRef get() = annotationTypeRef
override val annotations: List<FirAnnotation> get() = emptyList()
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {
annotationTypeRef.accept(visitor, data)
typeArguments.forEach { it.accept(visitor, data) }
argumentList.accept(visitor, data)
calleeReference.accept(visitor, data)
}
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirErrorAnnotationCallImpl {
transformAnnotationTypeRef(transformer, data)
transformTypeArguments(transformer, data)
argumentList = argumentList.transform(transformer, data)
transformCalleeReference(transformer, data)
return this
}
override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirErrorAnnotationCallImpl {
return this
}
override fun <D> transformAnnotationTypeRef(transformer: FirTransformer<D>, data: D): FirErrorAnnotationCallImpl {
annotationTypeRef = annotationTypeRef.transform(transformer, data)
return this
}
override fun <D> transformTypeArguments(transformer: FirTransformer<D>, data: D): FirErrorAnnotationCallImpl {
typeArguments.transformInplace(transformer, data)
return this
}
override fun <D> transformCalleeReference(transformer: FirTransformer<D>, data: D): FirErrorAnnotationCallImpl {
calleeReference = calleeReference.transform(transformer, data)
return this
}
override fun replaceTypeRef(newTypeRef: FirTypeRef) {}
override fun replaceTypeArguments(newTypeArguments: List<FirTypeProjection>) {
typeArguments.clear()
typeArguments.addAll(newTypeArguments)
}
override fun replaceArgumentList(newArgumentList: FirArgumentList) {
argumentList = newArgumentList
}
override fun replaceCalleeReference(newCalleeReference: FirReference) {
calleeReference = newCalleeReference
}
override fun replaceArgumentMapping(newArgumentMapping: FirAnnotationArgumentMapping) {
argumentMapping = newArgumentMapping
}
}
@@ -73,6 +73,7 @@ import org.jetbrains.kotlin.fir.expressions.FirCall
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.fir.expressions.FirAnnotationArgumentMapping
import org.jetbrains.kotlin.fir.expressions.FirErrorAnnotationCall
import org.jetbrains.kotlin.fir.expressions.FirComparisonExpression
import org.jetbrains.kotlin.fir.expressions.FirTypeOperatorCall
import org.jetbrains.kotlin.fir.expressions.FirAssignmentOperatorStatement
@@ -73,6 +73,7 @@ import org.jetbrains.kotlin.fir.expressions.FirCall
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.fir.expressions.FirAnnotationArgumentMapping
import org.jetbrains.kotlin.fir.expressions.FirErrorAnnotationCall
import org.jetbrains.kotlin.fir.expressions.FirComparisonExpression
import org.jetbrains.kotlin.fir.expressions.FirTypeOperatorCall
import org.jetbrains.kotlin.fir.expressions.FirAssignmentOperatorStatement
@@ -73,6 +73,7 @@ import org.jetbrains.kotlin.fir.expressions.FirCall
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.fir.expressions.FirAnnotationArgumentMapping
import org.jetbrains.kotlin.fir.expressions.FirErrorAnnotationCall
import org.jetbrains.kotlin.fir.expressions.FirComparisonExpression
import org.jetbrains.kotlin.fir.expressions.FirTypeOperatorCall
import org.jetbrains.kotlin.fir.expressions.FirAssignmentOperatorStatement
@@ -417,6 +418,10 @@ abstract class FirTransformer<in D> : FirVisitor<FirElement, D>() {
return transformElement(annotationArgumentMapping, data)
}
open fun transformErrorAnnotationCall(errorAnnotationCall: FirErrorAnnotationCall, data: D): FirStatement {
return transformElement(errorAnnotationCall, data)
}
open fun transformComparisonExpression(comparisonExpression: FirComparisonExpression, data: D): FirStatement {
return transformElement(comparisonExpression, data)
}
@@ -953,6 +958,10 @@ abstract class FirTransformer<in D> : FirVisitor<FirElement, D>() {
return transformAnnotationArgumentMapping(annotationArgumentMapping, data)
}
final override fun visitErrorAnnotationCall(errorAnnotationCall: FirErrorAnnotationCall, data: D): FirStatement {
return transformErrorAnnotationCall(errorAnnotationCall, data)
}
final override fun visitComparisonExpression(comparisonExpression: FirComparisonExpression, data: D): FirStatement {
return transformComparisonExpression(comparisonExpression, data)
}
@@ -73,6 +73,7 @@ import org.jetbrains.kotlin.fir.expressions.FirCall
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.fir.expressions.FirAnnotationArgumentMapping
import org.jetbrains.kotlin.fir.expressions.FirErrorAnnotationCall
import org.jetbrains.kotlin.fir.expressions.FirComparisonExpression
import org.jetbrains.kotlin.fir.expressions.FirTypeOperatorCall
import org.jetbrains.kotlin.fir.expressions.FirAssignmentOperatorStatement
@@ -282,6 +283,8 @@ abstract class FirVisitor<out R, in D> {
open fun visitAnnotationArgumentMapping(annotationArgumentMapping: FirAnnotationArgumentMapping, data: D): R = visitElement(annotationArgumentMapping, data)
open fun visitErrorAnnotationCall(errorAnnotationCall: FirErrorAnnotationCall, data: D): R = visitElement(errorAnnotationCall, data)
open fun visitComparisonExpression(comparisonExpression: FirComparisonExpression, data: D): R = visitElement(comparisonExpression, data)
open fun visitTypeOperatorCall(typeOperatorCall: FirTypeOperatorCall, data: D): R = visitElement(typeOperatorCall, data)
@@ -73,6 +73,7 @@ import org.jetbrains.kotlin.fir.expressions.FirCall
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.fir.expressions.FirAnnotationArgumentMapping
import org.jetbrains.kotlin.fir.expressions.FirErrorAnnotationCall
import org.jetbrains.kotlin.fir.expressions.FirComparisonExpression
import org.jetbrains.kotlin.fir.expressions.FirTypeOperatorCall
import org.jetbrains.kotlin.fir.expressions.FirAssignmentOperatorStatement
@@ -416,6 +417,10 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
visitElement(annotationArgumentMapping)
}
open fun visitErrorAnnotationCall(errorAnnotationCall: FirErrorAnnotationCall) {
visitElement(errorAnnotationCall)
}
open fun visitComparisonExpression(comparisonExpression: FirComparisonExpression) {
visitElement(comparisonExpression)
}
@@ -952,6 +957,10 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
visitAnnotationArgumentMapping(annotationArgumentMapping)
}
final override fun visitErrorAnnotationCall(errorAnnotationCall: FirErrorAnnotationCall, data: Nothing?) {
visitErrorAnnotationCall(errorAnnotationCall)
}
final override fun visitComparisonExpression(comparisonExpression: FirComparisonExpression, data: Nothing?) {
visitComparisonExpression(comparisonExpression)
}
@@ -69,6 +69,7 @@ enum class DiagnosticKind {
MissingStdlibClass,
NotASupertype,
SuperNotAvailable,
AnnotationNotAllowed,
LoopInSupertype,
RecursiveTypealiasExpansion,
@@ -122,6 +122,14 @@ object BuilderConfigurator : AbstractBuilderConfigurator<FirTreeBuilder>(FirTree
useTypes(emptyArgumentListType, emptyAnnotationArgumentMappingType, implicitTypeRefType)
}
builder(errorAnnotationCall) {
parents += callBuilder
default("argumentList", "FirEmptyArgumentList")
default("argumentMapping", "FirEmptyAnnotationArgumentMapping")
default("annotationTypeRef", "FirImplicitTypeRefImpl(null)")
useTypes(emptyArgumentListType, emptyAnnotationArgumentMappingType, implicitTypeRefType)
}
builder(arrayOfCall) {
parents += callBuilder
}
@@ -94,6 +94,7 @@ object FirTreeBuilder : AbstractFirTreeBuilder() {
val annotation by element(Expression, expression)
val annotationCall by element(Expression, annotation, call, resolvable)
val annotationArgumentMapping by element(Expression)
val errorAnnotationCall by element(Expression, annotationCall, diagnosticHolder)
val comparisonExpression by element(Expression, expression)
val typeOperatorCall by element(Expression, expression, call)
val assignmentOperatorStatement by element(Expression, statement)
@@ -96,6 +96,13 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
}
}
impl(errorAnnotationCall) {
commonAnnotationConfig()
default("argumentMapping") {
needAcceptAndTransform = false
}
}
impl(arrayOfCall)
impl(callableReferenceAccess)
@@ -469,6 +469,10 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(FirTreeBuild
+field("argumentMapping", annotationArgumentMapping, withReplace = true)
}
errorAnnotationCall.configure {
+field("argumentMapping", annotationArgumentMapping, withReplace = true)
}
annotationArgumentMapping.configure {
+field("mapping", type("Map") to listOf(nameType, expression))
}
@@ -343,6 +343,8 @@ public interface Errors {
DiagnosticFactory0<PsiElement> NON_PARENTHESIZED_ANNOTATIONS_ON_FUNCTIONAL_TYPES = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtAnnotationEntry> ANNOTATION_IN_WHERE_CLAUSE_WARNING = DiagnosticFactory0.create(WARNING);
// Const
DiagnosticFactory0<PsiElement> CONST_VAL_NOT_TOP_LEVEL_OR_OBJECT = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<PsiElement> CONST_VAL_WITH_GETTER = DiagnosticFactory0.create(ERROR);
@@ -187,6 +187,8 @@ public class DefaultErrorMessages {
MAP.put(NON_PARENTHESIZED_ANNOTATIONS_ON_FUNCTIONAL_TYPES, "Non-parenthesized annotations on function types without receiver aren't yet supported (see KT-31734 for details)");
MAP.put(ANNOTATION_IN_WHERE_CLAUSE_WARNING, "Type parameter annotations will not be allowed inside where clauses in future releases. You should probably move annotations to the type parameter declaration");
MAP.put(REDUNDANT_MODIFIER, "Modifier ''{0}'' is redundant because ''{1}'' is present", TO_STRING, TO_STRING);
MAP.put(REDUNDANT_OPEN_IN_INTERFACE, "Modifier 'open' is redundant for abstract interface members");
MAP.put(REDUNDANT_MODIFIER_IN_GETTER, "Visibility modifiers are redundant in getter");
@@ -537,6 +537,12 @@ class DeclarationsChecker(
checkSupertypesForConsistency(typeParameterDescriptor, typeParameter)
checkOnlyOneTypeParameterBound(typeParameterDescriptor, typeParameter, typeParameterListOwner)
}
for (constraint in constraints) {
constraint.annotationEntries.forEach {
trace.report(ANNOTATION_IN_WHERE_CLAUSE_WARNING.on(it))
}
}
}
private fun checkConstructorInInterface(klass: KtClass) {
@@ -19,10 +19,15 @@ package org.jetbrains.kotlin.psi;
import com.intellij.lang.ASTNode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.KtNodeTypes;
import org.jetbrains.kotlin.psi.psiUtil.KtPsiUtilKt;
import org.jetbrains.kotlin.psi.stubs.KotlinPlaceHolderStub;
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes;
public class KtTypeConstraint extends KtElementImplStub<KotlinPlaceHolderStub<KtTypeConstraint>> {
import java.util.List;
public class KtTypeConstraint extends KtElementImplStub<KotlinPlaceHolderStub<KtTypeConstraint>>
implements KtAnnotated, KtAnnotationsContainer {
public KtTypeConstraint(@NotNull ASTNode node) {
super(node);
}
@@ -45,4 +50,16 @@ public class KtTypeConstraint extends KtElementImplStub<KotlinPlaceHolderStub<Kt
public KtTypeReference getBoundTypeReference() {
return getStubOrPsiChild(KtStubElementTypes.TYPE_REFERENCE);
}
@Override
@NotNull
public List<KtAnnotation> getAnnotations() {
return findChildrenByType(KtNodeTypes.ANNOTATION);
}
@Override
@NotNull
public List<KtAnnotationEntry> getAnnotationEntries() {
return KtPsiUtilKt.collectAnnotationEntriesFromStubOrPsi(this);
}
}
+11
View File
@@ -0,0 +1,11 @@
@Repeatable
@Target( AnnotationTarget.TYPE_PARAMETER)
annotation class TypeParameterAnn(val name: String)
interface Generic<Z>
fun <<!MISPLACED_TYPE_PARAMETER_CONSTRAINTS!>@TypeParameterAnn("T") T: Any<!>> whereClauseWithAnnotation() where <!ANNOTATION_IN_WHERE_CLAUSE_ERROR!>@TypeParameterAnn("Prohibit me!!!")<!> T : Generic<String> {
}
class Foo<<!MISPLACED_TYPE_PARAMETER_CONSTRAINTS!>@TypeParameterAnn("T") T: Any<!>> () where <!ANNOTATION_IN_WHERE_CLAUSE_ERROR!>@TypeParameterAnn("Prohibit me!!!")<!> T : Generic<String> {
}
+11
View File
@@ -0,0 +1,11 @@
@Repeatable
@Target( AnnotationTarget.TYPE_PARAMETER)
annotation class TypeParameterAnn(val name: String)
interface Generic<Z>
fun <<!MISPLACED_TYPE_PARAMETER_CONSTRAINTS!>@TypeParameterAnn("T") T: Any<!>> whereClauseWithAnnotation() where <!ANNOTATION_IN_WHERE_CLAUSE_WARNING!>@<!DEBUG_INFO_MISSING_UNRESOLVED!>TypeParameterAnn<!>("Prohibit me!!!")<!> T : Generic<String> {
}
class Foo<<!MISPLACED_TYPE_PARAMETER_CONSTRAINTS!>@TypeParameterAnn("T") T: Any<!>> () where <!ANNOTATION_IN_WHERE_CLAUSE_WARNING!>@<!DEBUG_INFO_MISSING_UNRESOLVED!>TypeParameterAnn<!>("Prohibit me!!!")<!> T : Generic<String> {
}
+24
View File
@@ -0,0 +1,24 @@
package
public fun </*0*/ @TypeParameterAnn(name = "T") T : kotlin.Any> whereClauseWithAnnotation(): kotlin.Unit where T : Generic<kotlin.String>
public final class Foo</*0*/ @TypeParameterAnn(name = "T") T : kotlin.Any> where T : Generic<kotlin.String> {
public constructor Foo</*0*/ @TypeParameterAnn(name = "T") T : kotlin.Any>() where T : Generic<kotlin.String>
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface Generic</*0*/ Z> {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@kotlin.annotation.Repeatable @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE_PARAMETER}) public final annotation class TypeParameterAnn : kotlin.Annotation {
public constructor TypeParameterAnn(/*0*/ name: kotlin.String)
public final val name: kotlin.String
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -423,6 +423,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/kt435.kt");
}
@Test
@TestMetadata("kt46483.kt")
public void testKt46483() throws Exception {
runTest("compiler/testData/diagnostics/tests/kt46483.kt");
}
@Test
@TestMetadata("kt49438.kt")
public void testKt49438() throws Exception {
@@ -9,4 +9,4 @@ abstract class Bar<T : @Ann(<!UNRESOLVED_REFERENCE!>unresolved_reference<!>) Any
* TESTCASE NUMBER: 2
* UNEXPECTED BEHAVIOUR
*/
class B<T> where @Ann(unresolved_reference) T : Number
class B<T> where <!ANNOTATION_IN_WHERE_CLAUSE_ERROR, WRONG_ANNOTATION_TARGET!>@Ann(<!UNRESOLVED_REFERENCE!>unresolved_reference<!>)<!> T : Number
@@ -18,4 +18,4 @@ abstract class Bar<T : @Ann(<!UNRESOLVED_REFERENCE!>unresolved_reference<!>) Any
* TESTCASE NUMBER: 2
* UNEXPECTED BEHAVIOUR
*/
class B<T> where @<!DEBUG_INFO_MISSING_UNRESOLVED!>Ann<!>(<!DEBUG_INFO_MISSING_UNRESOLVED!>unresolved_reference<!>) T : Number
class B<T> where <!ANNOTATION_IN_WHERE_CLAUSE_WARNING!>@<!DEBUG_INFO_MISSING_UNRESOLVED!>Ann<!>(<!DEBUG_INFO_MISSING_UNRESOLVED!>unresolved_reference<!>)<!> T : Number