diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt index 107a21ba47a..981fc6bd204 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt @@ -332,6 +332,8 @@ object DIAGNOSTICS_LIST : DiagnosticList() { } val CYCLIC_GENERIC_UPPER_BOUND by error() + + val DEPRECATED_TYPE_PARAMETER_SYNTAX by error() } val REFLECTION by object : DiagnosticGroup("Reflection") { diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt index 59f937bc5ec..f41820f5b8b 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt @@ -241,6 +241,7 @@ object FirErrors { val TYPE_PARAMETER_OF_PROPERTY_NOT_USED_IN_RECEIVER by error0() val RETURN_TYPE_MISMATCH by error2(SourceElementPositioningStrategies.WHOLE_ELEMENT) val CYCLIC_GENERIC_UPPER_BOUND by error0() + val DEPRECATED_TYPE_PARAMETER_SYNTAX by error0() // Reflection val EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED by error1>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirCyclicTypeBoundsChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirCyclicTypeBoundsChecker.kt index d06f5754e95..5f31d3fe90e 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirCyclicTypeBoundsChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirCyclicTypeBoundsChecker.kt @@ -44,6 +44,7 @@ object FirCyclicTypeBoundsChecker : FirMemberDeclarationChecker() { declaration.typeParameters .filter { cycles.contains(it.symbol.name) } .forEach { param -> + //for some reason FE 1.0 report differently for class declarations val targets = if (declaration is FirRegularClass) { param.symbol.fir.originalBounds().filter { cycles.contains(extractTypeParamName(it.coneType)) } .mapNotNull { it.source } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirFunctionTypeParametersChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirFunctionTypeParametersChecker.kt new file mode 100644 index 00000000000..bed36d194cb --- /dev/null +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirFunctionTypeParametersChecker.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2010-2021 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.checkers.declaration + +import org.jetbrains.kotlin.fir.FirFakeSourceElement +import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext +import org.jetbrains.kotlin.fir.analysis.diagnostics.* +import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction +import org.jetbrains.kotlin.fir.toFirLightSourceElement + +object FirFunctionTypeParametersChecker : FirSimpleFunctionChecker() { + + override fun check(declaration: FirSimpleFunction, context: CheckerContext, reporter: DiagnosticReporter) { + declaration.source?.let { source -> + if (source is FirFakeSourceElement<*>) return + + val typeParamsNode = source.treeStructure.typeParametersList(source.lighterASTNode) + val nameNode = source.treeStructure.nameIdentifier(source.lighterASTNode) + if (typeParamsNode != null && nameNode != null && typeParamsNode.startOffset > nameNode.startOffset) { + reporter.reportOn( + typeParamsNode.toFirLightSourceElement(source.treeStructure), + FirErrors.DEPRECATED_TYPE_PARAMETER_SYNTAX, + context + ) + } + } + } +} diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt index 290cee9c4cd..633449222a5 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt @@ -79,6 +79,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DELEGATED_PROPERT import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DELEGATION_IN_INTERFACE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DELEGATION_SUPER_CALL_IN_ENUM_CONSTRUCTOR import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DEPRECATED_MODIFIER_PAIR +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DEPRECATED_TYPE_PARAMETER_SYNTAX import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DESERIALIZATION_ERROR import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EMPTY_RANGE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ENUM_AS_SUPERTYPE @@ -512,6 +513,8 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension { map.put(CYCLIC_GENERIC_UPPER_BOUND, "Type parameter has cyclic upper bounds") + map.put(DEPRECATED_TYPE_PARAMETER_SYNTAX, "Type parameters must be placed before the name of the function") + // Reflection map.put( EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED, diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/LightTreePositioningStrategies.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/LightTreePositioningStrategies.kt index afcb466c748..e29f2e9cbd3 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/LightTreePositioningStrategies.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/LightTreePositioningStrategies.kt @@ -577,7 +577,7 @@ private fun FlyweightCapableTreeStructure.ifKeyword(node: Lighte private fun FlyweightCapableTreeStructure.returnKeyword(node: LighterASTNode): LighterASTNode? = findChildByType(node, KtTokens.RETURN_KEYWORD) -private fun FlyweightCapableTreeStructure.nameIdentifier(node: LighterASTNode): LighterASTNode? = +internal fun FlyweightCapableTreeStructure.nameIdentifier(node: LighterASTNode): LighterASTNode? = findChildByType(node, KtTokens.IDENTIFIER) private fun FlyweightCapableTreeStructure.operationReference(node: LighterASTNode): LighterASTNode? = diff --git a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/checkers/CommonDeclarationCheckers.kt b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/checkers/CommonDeclarationCheckers.kt index d86647826c3..75948209e94 100644 --- a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/checkers/CommonDeclarationCheckers.kt +++ b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/checkers/CommonDeclarationCheckers.kt @@ -35,7 +35,8 @@ object CommonDeclarationCheckers : DeclarationCheckers() { ) override val simpleFunctionCheckers: Set = setOf( - FirFunctionNameChecker + FirFunctionNameChecker, + FirFunctionTypeParametersChecker, ) override val propertyCheckers: Set = setOf( diff --git a/compiler/testData/diagnostics/tests/typeParameters/deprecatedSyntax.fir.kt b/compiler/testData/diagnostics/tests/typeParameters/deprecatedSyntax.fir.kt deleted file mode 100644 index 25cf191662a..00000000000 --- a/compiler/testData/diagnostics/tests/typeParameters/deprecatedSyntax.fir.kt +++ /dev/null @@ -1,3 +0,0 @@ -fun foo() { - fun bar() {} -} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/typeParameters/deprecatedSyntax.kt b/compiler/testData/diagnostics/tests/typeParameters/deprecatedSyntax.kt index d1dba42ad9c..95daea9122b 100644 --- a/compiler/testData/diagnostics/tests/typeParameters/deprecatedSyntax.kt +++ b/compiler/testData/diagnostics/tests/typeParameters/deprecatedSyntax.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL fun foo() { fun bar() {} } \ No newline at end of file diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt index 594c42d159b..3953dc86e25 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt @@ -1024,6 +1024,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert token, ) } + add(FirErrors.DEPRECATED_TYPE_PARAMETER_SYNTAX) { firDiagnostic -> + DeprecatedTypeParameterSyntaxImpl( + firDiagnostic as FirPsiDiagnostic<*>, + token, + ) + } add(FirErrors.EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED) { firDiagnostic -> ExtensionInClassReferenceNotAllowedImpl( firSymbolBuilder.callableBuilder.buildCallableSymbol(firDiagnostic.a as FirCallableDeclaration), diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt index 6febbd4abc1..b0594f94b9c 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt @@ -723,10 +723,14 @@ sealed class KtFirDiagnostic : KtDiagnosticWithPsi { abstract val actual: KtType } - abstract class CyclicGenericUpperBound : KtFirDiagnostic() { + abstract class CyclicGenericUpperBound : KtFirDiagnostic() { override val diagnosticClass get() = CyclicGenericUpperBound::class } + abstract class DeprecatedTypeParameterSyntax : KtFirDiagnostic() { + override val diagnosticClass get() = DeprecatedTypeParameterSyntax::class + } + abstract class ExtensionInClassReferenceNotAllowed : KtFirDiagnostic() { override val diagnosticClass get() = ExtensionInClassReferenceNotAllowed::class abstract val referencedDeclaration: KtCallableSymbol diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt index ac0a9e27a29..7414fb17309 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt @@ -1171,7 +1171,14 @@ internal class ReturnTypeMismatchImpl( internal class CyclicGenericUpperBoundImpl( firDiagnostic: FirPsiDiagnostic<*>, override val token: ValidityToken, -) : KtFirDiagnostic.CyclicGenericUpperBound(), KtAbstractFirDiagnostic { +) : KtFirDiagnostic.CyclicGenericUpperBound(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) +} + +internal class DeprecatedTypeParameterSyntaxImpl( + firDiagnostic: FirPsiDiagnostic<*>, + override val token: ValidityToken, +) : KtFirDiagnostic.DeprecatedTypeParameterSyntax(), KtAbstractFirDiagnostic { override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) }