提交 a564f92e 编写于 作者: E eugenpolytechnic 提交者: Mikhail Glukhikh

FIR: introduce ThrowableSubclassChecker

上级 cd189c08
...@@ -419,6 +419,11 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract ...@@ -419,6 +419,11 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract
runTest("compiler/fir/analysis-tests/testData/resolve/syntheticsVsNormalProperties.kt"); runTest("compiler/fir/analysis-tests/testData/resolve/syntheticsVsNormalProperties.kt");
} }
@TestMetadata("throwableSubclass.kt")
public void testThrowableSubclass() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/throwableSubclass.kt");
}
@TestMetadata("treeSet.kt") @TestMetadata("treeSet.kt")
public void testTreeSet() throws Exception { public void testTreeSet() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/treeSet.kt"); runTest("compiler/fir/analysis-tests/testData/resolve/treeSet.kt");
......
FILE: throwableSubclass.kt
public final class Test1<T, B> : R|kotlin/Exception| {
public constructor<T, B>(): R|Test1<T, B>| {
super<R|kotlin/Exception|>()
}
public final inner class Test2<S, T, B> : R|kotlin/Throwable| {
public constructor<S>(): R|Test1.Test2<S, T, B>| {
super<R|kotlin/Throwable|>()
}
}
public final class Test3 : R|kotlin/NullPointerException| {
public constructor(): R|Test1.Test3| {
super<R|kotlin/NullPointerException|>()
}
}
public final object Test4 : R|kotlin/Throwable| {
private constructor(): R|Test1.Test4| {
super<R|kotlin/Throwable|>()
}
}
}
public final class Test5<T, B> : R|kotlin/Any| {
public constructor<T, B>(): R|Test5<T, B>| {
super<R|kotlin/Any|>()
}
public final inner class Test6<T, B> : R|kotlin/Exception| {
public constructor(): R|Test5.Test6<T, B>| {
super<R|kotlin/Exception|>()
}
}
public final fun foo(): R|kotlin/Unit| {
local final class Test7 : R|kotlin/Throwable| {
public constructor(): R|Test5.Test7| {
super<R|kotlin/Throwable|>()
}
}
}
}
public final fun <Z> topLevelFun(): R|kotlin/Unit| {
local final class Test8 : R|kotlin/Error| {
public constructor(): R|Test8| {
super<R|kotlin/Error|>()
}
}
lval obj: R|<anonymous><Z>| = object : R|kotlin/Throwable| {
private constructor(): R|<anonymous><Z>| {
super<R|kotlin/Throwable|>()
}
}
}
class Test1<<!GENERIC_THROWABLE_SUBCLASS!>T<!>, B> : Exception() {
inner <!INNER_CLASS_OF_GENERIC_THROWABLE_SUBCLASS!>class Test2<!><<!GENERIC_THROWABLE_SUBCLASS!>S<!>> : Throwable()
class Test3 : NullPointerException()
object Test4 : Throwable() {}
}
class Test5<T, B> {
inner <!INNER_CLASS_OF_GENERIC_THROWABLE_SUBCLASS!>class Test6<!> : Exception()
fun foo() {
<!INNER_CLASS_OF_GENERIC_THROWABLE_SUBCLASS!>class Test7<!> : Throwable()
}
}
fun <Z> topLevelFun() {
<!INNER_CLASS_OF_GENERIC_THROWABLE_SUBCLASS!>class Test8<!> : Error()
val obj = <!INNER_CLASS_OF_GENERIC_THROWABLE_SUBCLASS{LT}!><!INNER_CLASS_OF_GENERIC_THROWABLE_SUBCLASS{PSI}!>object<!> : Throwable() {}<!>
}
...@@ -494,6 +494,12 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest { ...@@ -494,6 +494,12 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest {
runTest("compiler/fir/analysis-tests/testData/resolve/syntheticsVsNormalProperties.kt"); runTest("compiler/fir/analysis-tests/testData/resolve/syntheticsVsNormalProperties.kt");
} }
@Test
@TestMetadata("throwableSubclass.kt")
public void testThrowableSubclass() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/throwableSubclass.kt");
}
@Test @Test
@TestMetadata("treeSet.kt") @TestMetadata("treeSet.kt")
public void testTreeSet() throws Exception { public void testTreeSet() throws Exception {
......
...@@ -497,6 +497,12 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos ...@@ -497,6 +497,12 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
runTest("compiler/fir/analysis-tests/testData/resolve/syntheticsVsNormalProperties.kt"); runTest("compiler/fir/analysis-tests/testData/resolve/syntheticsVsNormalProperties.kt");
} }
@Test
@TestMetadata("throwableSubclass.kt")
public void testThrowableSubclass() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/throwableSubclass.kt");
}
@Test @Test
@TestMetadata("treeSet.kt") @TestMetadata("treeSet.kt")
public void testTreeSet() throws Exception { public void testTreeSet() throws Exception {
......
...@@ -31,6 +31,7 @@ fun main(args: Array<String>) { ...@@ -31,6 +31,7 @@ fun main(args: Array<String>) {
alias<FirMemberDeclaration>("MemberDeclarationChecker") alias<FirMemberDeclaration>("MemberDeclarationChecker")
alias<FirFunction<*>>("FunctionChecker") alias<FirFunction<*>>("FunctionChecker")
alias<FirProperty>("PropertyChecker") alias<FirProperty>("PropertyChecker")
alias<FirClass<*>>("ClassChecker")
alias<FirRegularClass>("RegularClassChecker") alias<FirRegularClass>("RegularClassChecker")
alias<FirConstructor>("ConstructorChecker") alias<FirConstructor>("ConstructorChecker")
alias<FirFile>("FileChecker") alias<FirFile>("FileChecker")
......
...@@ -23,6 +23,8 @@ internal class ComposedDeclarationCheckers : DeclarationCheckers() { ...@@ -23,6 +23,8 @@ internal class ComposedDeclarationCheckers : DeclarationCheckers() {
get() = _functionCheckers get() = _functionCheckers
override val propertyCheckers: Set<FirPropertyChecker> override val propertyCheckers: Set<FirPropertyChecker>
get() = _propertyCheckers get() = _propertyCheckers
override val classCheckers: Set<FirClassChecker>
get() = _classCheckers
override val regularClassCheckers: Set<FirRegularClassChecker> override val regularClassCheckers: Set<FirRegularClassChecker>
get() = _regularClassCheckers get() = _regularClassCheckers
override val constructorCheckers: Set<FirConstructorChecker> override val constructorCheckers: Set<FirConstructorChecker>
...@@ -38,6 +40,7 @@ internal class ComposedDeclarationCheckers : DeclarationCheckers() { ...@@ -38,6 +40,7 @@ internal class ComposedDeclarationCheckers : DeclarationCheckers() {
private val _memberDeclarationCheckers: MutableSet<FirMemberDeclarationChecker> = mutableSetOf() private val _memberDeclarationCheckers: MutableSet<FirMemberDeclarationChecker> = mutableSetOf()
private val _functionCheckers: MutableSet<FirFunctionChecker> = mutableSetOf() private val _functionCheckers: MutableSet<FirFunctionChecker> = mutableSetOf()
private val _propertyCheckers: MutableSet<FirPropertyChecker> = mutableSetOf() private val _propertyCheckers: MutableSet<FirPropertyChecker> = mutableSetOf()
private val _classCheckers: MutableSet<FirClassChecker> = mutableSetOf()
private val _regularClassCheckers: MutableSet<FirRegularClassChecker> = mutableSetOf() private val _regularClassCheckers: MutableSet<FirRegularClassChecker> = mutableSetOf()
private val _constructorCheckers: MutableSet<FirConstructorChecker> = mutableSetOf() private val _constructorCheckers: MutableSet<FirConstructorChecker> = mutableSetOf()
private val _fileCheckers: MutableSet<FirFileChecker> = mutableSetOf() private val _fileCheckers: MutableSet<FirFileChecker> = mutableSetOf()
...@@ -50,6 +53,7 @@ internal class ComposedDeclarationCheckers : DeclarationCheckers() { ...@@ -50,6 +53,7 @@ internal class ComposedDeclarationCheckers : DeclarationCheckers() {
_memberDeclarationCheckers += checkers.allMemberDeclarationCheckers _memberDeclarationCheckers += checkers.allMemberDeclarationCheckers
_functionCheckers += checkers.allFunctionCheckers _functionCheckers += checkers.allFunctionCheckers
_propertyCheckers += checkers.allPropertyCheckers _propertyCheckers += checkers.allPropertyCheckers
_classCheckers += checkers.allClassCheckers
_regularClassCheckers += checkers.allRegularClassCheckers _regularClassCheckers += checkers.allRegularClassCheckers
_constructorCheckers += checkers.allConstructorCheckers _constructorCheckers += checkers.allConstructorCheckers
_fileCheckers += checkers.allFileCheckers _fileCheckers += checkers.allFileCheckers
......
...@@ -23,6 +23,7 @@ abstract class DeclarationCheckers { ...@@ -23,6 +23,7 @@ abstract class DeclarationCheckers {
open val memberDeclarationCheckers: Set<FirMemberDeclarationChecker> = emptySet() open val memberDeclarationCheckers: Set<FirMemberDeclarationChecker> = emptySet()
open val functionCheckers: Set<FirFunctionChecker> = emptySet() open val functionCheckers: Set<FirFunctionChecker> = emptySet()
open val propertyCheckers: Set<FirPropertyChecker> = emptySet() open val propertyCheckers: Set<FirPropertyChecker> = emptySet()
open val classCheckers: Set<FirClassChecker> = emptySet()
open val regularClassCheckers: Set<FirRegularClassChecker> = emptySet() open val regularClassCheckers: Set<FirRegularClassChecker> = emptySet()
open val constructorCheckers: Set<FirConstructorChecker> = emptySet() open val constructorCheckers: Set<FirConstructorChecker> = emptySet()
open val fileCheckers: Set<FirFileChecker> = emptySet() open val fileCheckers: Set<FirFileChecker> = emptySet()
...@@ -34,7 +35,8 @@ abstract class DeclarationCheckers { ...@@ -34,7 +35,8 @@ abstract class DeclarationCheckers {
@CheckersComponentInternal internal val allMemberDeclarationCheckers: Set<FirMemberDeclarationChecker> get() = memberDeclarationCheckers + allBasicDeclarationCheckers @CheckersComponentInternal internal val allMemberDeclarationCheckers: Set<FirMemberDeclarationChecker> get() = memberDeclarationCheckers + allBasicDeclarationCheckers
@CheckersComponentInternal internal val allFunctionCheckers: Set<FirFunctionChecker> get() = functionCheckers + allBasicDeclarationCheckers @CheckersComponentInternal internal val allFunctionCheckers: Set<FirFunctionChecker> get() = functionCheckers + allBasicDeclarationCheckers
@CheckersComponentInternal internal val allPropertyCheckers: Set<FirPropertyChecker> get() = propertyCheckers + allMemberDeclarationCheckers @CheckersComponentInternal internal val allPropertyCheckers: Set<FirPropertyChecker> get() = propertyCheckers + allMemberDeclarationCheckers
@CheckersComponentInternal internal val allRegularClassCheckers: Set<FirRegularClassChecker> get() = regularClassCheckers + allMemberDeclarationCheckers @CheckersComponentInternal internal val allClassCheckers: Set<FirClassChecker> get() = classCheckers + allBasicDeclarationCheckers
@CheckersComponentInternal internal val allRegularClassCheckers: Set<FirRegularClassChecker> get() = regularClassCheckers + allMemberDeclarationCheckers + allClassCheckers
@CheckersComponentInternal internal val allConstructorCheckers: Set<FirConstructorChecker> get() = constructorCheckers + allFunctionCheckers @CheckersComponentInternal internal val allConstructorCheckers: Set<FirConstructorChecker> get() = constructorCheckers + allFunctionCheckers
@CheckersComponentInternal internal val allFileCheckers: Set<FirFileChecker> get() = fileCheckers + allBasicDeclarationCheckers @CheckersComponentInternal internal val allFileCheckers: Set<FirFileChecker> get() = fileCheckers + allBasicDeclarationCheckers
} }
...@@ -10,6 +10,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration ...@@ -10,6 +10,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration
* DO NOT MODIFY IT MANUALLY * DO NOT MODIFY IT MANUALLY
*/ */
import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.FirConstructor import org.jetbrains.kotlin.fir.declarations.FirConstructor
import org.jetbrains.kotlin.fir.declarations.FirDeclaration import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.FirFile import org.jetbrains.kotlin.fir.declarations.FirFile
...@@ -22,6 +23,7 @@ typealias FirBasicDeclarationChecker = FirDeclarationChecker<FirDeclaration> ...@@ -22,6 +23,7 @@ typealias FirBasicDeclarationChecker = FirDeclarationChecker<FirDeclaration>
typealias FirMemberDeclarationChecker = FirDeclarationChecker<FirMemberDeclaration> typealias FirMemberDeclarationChecker = FirDeclarationChecker<FirMemberDeclaration>
typealias FirFunctionChecker = FirDeclarationChecker<FirFunction<*>> typealias FirFunctionChecker = FirDeclarationChecker<FirFunction<*>>
typealias FirPropertyChecker = FirDeclarationChecker<FirProperty> typealias FirPropertyChecker = FirDeclarationChecker<FirProperty>
typealias FirClassChecker = FirDeclarationChecker<FirClass<*>>
typealias FirRegularClassChecker = FirDeclarationChecker<FirRegularClass> typealias FirRegularClassChecker = FirDeclarationChecker<FirRegularClass>
typealias FirConstructorChecker = FirDeclarationChecker<FirConstructor> typealias FirConstructorChecker = FirDeclarationChecker<FirConstructor>
typealias FirFileChecker = FirDeclarationChecker<FirFile> typealias FirFileChecker = FirDeclarationChecker<FirFile>
...@@ -38,6 +38,7 @@ import org.jetbrains.kotlin.fir.types.* ...@@ -38,6 +38,7 @@ import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtModifierList import org.jetbrains.kotlin.psi.KtModifierList
import org.jetbrains.kotlin.psi.KtObjectLiteralExpression
import org.jetbrains.kotlin.psi.psiUtil.visibilityModifierType import org.jetbrains.kotlin.psi.psiUtil.visibilityModifierType
import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.kotlin.utils.addToStdlib.safeAs
...@@ -318,3 +319,9 @@ fun Modality.toToken(): KtModifierKeywordToken = when (this) { ...@@ -318,3 +319,9 @@ fun Modality.toToken(): KtModifierKeywordToken = when (this) {
val FirFunctionCall.isIterator val FirFunctionCall.isIterator
get() = this.calleeReference.name.asString() == "<iterator>" get() = this.calleeReference.name.asString() == "<iterator>"
internal val throwableClassLikeType =
StandardClassIds.byName("Throwable").constructClassLikeType(emptyArray(), false)
fun ConeKotlinType.isThrowable(session: FirSession) =
throwableClassLikeType.isSupertypeOf(session.typeCheckerContext, this.fullyExpandedType(session))
\ No newline at end of file
/*
* 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.FirSourceElement
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.isThrowable
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.types.ConeClassErrorType
object FirThrowableSubclassChecker : FirClassChecker() {
override fun check(declaration: FirClass<*>, context: CheckerContext, reporter: DiagnosticReporter) {
if (!declaration.hasThrowableSupertype(context))
return
if (declaration.typeParameters.isNotEmpty()) {
reporter.reportGenericThrowableSubclass(declaration.typeParameters.firstOrNull()?.source)
val source = when {
(declaration as? FirRegularClass)?.isInner == true -> declaration.source
declaration is FirAnonymousObject -> (declaration.declarations.firstOrNull())?.source
else -> null
}
reporter.reportInnerClassOfGenericThrowableSubclass(source)
} else if (declaration.hasGenericOuterDeclaration(context)) {
reporter.reportInnerClassOfGenericThrowableSubclass(declaration.source)
}
}
private fun FirClass<*>.hasThrowableSupertype(context: CheckerContext) =
superConeTypes.any { it !is ConeClassErrorType && it.isThrowable(context.session) }
private fun FirClass<*>.hasGenericOuterDeclaration(context: CheckerContext) =
classId.isLocal && context.containingDeclarations.anyIsGeneric()
private fun Collection<FirDeclaration>.anyIsGeneric() =
any { it is FirTypeParameterRefsOwner && it.typeParameters.isNotEmpty() }
private fun DiagnosticReporter.reportGenericThrowableSubclass(source: FirSourceElement?) {
source?.let { report(FirErrors.GENERIC_THROWABLE_SUBCLASS.on(it)) }
}
private fun DiagnosticReporter.reportInnerClassOfGenericThrowableSubclass(source: FirSourceElement?) {
source?.let { report(FirErrors.INNER_CLASS_OF_GENERIC_THROWABLE_SUBCLASS.on(it)) }
}
}
\ No newline at end of file
...@@ -8,6 +8,8 @@ package org.jetbrains.kotlin.fir.analysis.checkers.expression ...@@ -8,6 +8,8 @@ package org.jetbrains.kotlin.fir.analysis.checkers.expression
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.cfa.FirReturnsImpliesAnalyzer.isSupertypeOf import org.jetbrains.kotlin.fir.analysis.cfa.FirReturnsImpliesAnalyzer.isSupertypeOf
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.isThrowable
import org.jetbrains.kotlin.fir.analysis.checkers.throwableClassLikeType
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.expressions.FirTryExpression import org.jetbrains.kotlin.fir.expressions.FirTryExpression
...@@ -20,9 +22,6 @@ import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef ...@@ -20,9 +22,6 @@ import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.fir.types.constructClassLikeType import org.jetbrains.kotlin.fir.types.constructClassLikeType
object FirCatchParameterChecker : FirTryExpressionChecker() { object FirCatchParameterChecker : FirTryExpressionChecker() {
private val throwable = StandardClassIds.byName("Throwable")
.constructClassLikeType(emptyArray(), false)
override fun check(expression: FirTryExpression, context: CheckerContext, reporter: DiagnosticReporter) { override fun check(expression: FirTryExpression, context: CheckerContext, reporter: DiagnosticReporter) {
for (catchEntry in expression.catches) { for (catchEntry in expression.catches) {
val catchParameter = catchEntry.parameter val catchParameter = catchEntry.parameter
...@@ -45,10 +44,7 @@ object FirCatchParameterChecker : FirTryExpressionChecker() { ...@@ -45,10 +44,7 @@ object FirCatchParameterChecker : FirTryExpressionChecker() {
} }
if (!coneType.isThrowable(context.session)) if (!coneType.isThrowable(context.session))
catchParameter.source?.let { reporter.report(FirErrors.TYPE_MISMATCH.on(it, throwable, coneType), context) } catchParameter.source?.let { reporter.report(FirErrors.TYPE_MISMATCH.on(it, throwableClassLikeType, coneType), context) }
} }
} }
private fun ConeKotlinType.isThrowable(session: FirSession) =
throwable.isSupertypeOf(session.typeCheckerContext, this.fullyExpandedType(session))
} }
...@@ -25,6 +25,10 @@ class DeclarationCheckersDiagnosticComponent( ...@@ -25,6 +25,10 @@ class DeclarationCheckersDiagnosticComponent(
(checkers.memberDeclarationCheckers + checkers.propertyCheckers).check(property, data, reporter) (checkers.memberDeclarationCheckers + checkers.propertyCheckers).check(property, data, reporter)
} }
override fun <F : FirClass<F>> visitClass(klass: FirClass<F>, data: CheckerContext) {
checkers.classCheckers.check(klass, data, reporter)
}
override fun visitRegularClass(regularClass: FirRegularClass, data: CheckerContext) { override fun visitRegularClass(regularClass: FirRegularClass, data: CheckerContext) {
checkers.regularClassCheckers.check(regularClass, data, reporter) checkers.regularClassCheckers.check(regularClass, data, reporter)
} }
...@@ -62,7 +66,7 @@ class DeclarationCheckersDiagnosticComponent( ...@@ -62,7 +66,7 @@ class DeclarationCheckersDiagnosticComponent(
} }
override fun visitAnonymousObject(anonymousObject: FirAnonymousObject, data: CheckerContext) { override fun visitAnonymousObject(anonymousObject: FirAnonymousObject, data: CheckerContext) {
checkers.basicDeclarationCheckers.check(anonymousObject, data, reporter) (checkers.classCheckers + checkers.basicDeclarationCheckers).check(anonymousObject, data, reporter)
} }
override fun visitAnonymousInitializer(anonymousInitializer: FirAnonymousInitializer, data: CheckerContext) { override fun visitAnonymousInitializer(anonymousInitializer: FirAnonymousInitializer, data: CheckerContext) {
......
...@@ -71,6 +71,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPOSED_SUPER_INT ...@@ -71,6 +71,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPOSED_SUPER_INT
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPOSED_TYPEALIAS_EXPANDED_TYPE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPOSED_TYPEALIAS_EXPANDED_TYPE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPOSED_TYPE_PARAMETER_BOUND import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPOSED_TYPE_PARAMETER_BOUND
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FUNCTION_DECLARATION_WITH_NO_NAME import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FUNCTION_DECLARATION_WITH_NO_NAME
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.GENERIC_THROWABLE_SUBCLASS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.HIDDEN import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.HIDDEN
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ILLEGAL_CONST_EXPRESSION import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ILLEGAL_CONST_EXPRESSION
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ILLEGAL_UNDERSCORE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ILLEGAL_UNDERSCORE
...@@ -80,6 +81,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INAPPLICABLE_LATE ...@@ -80,6 +81,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INAPPLICABLE_LATE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INCOMPATIBLE_MODIFIERS import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INCOMPATIBLE_MODIFIERS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INFERENCE_ERROR import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INFERENCE_ERROR
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INNER_CLASS_OF_GENERIC_THROWABLE_SUBCLASS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INSTANCE_ACCESS_BEFORE_SUPER_CALL import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INSTANCE_ACCESS_BEFORE_SUPER_CALL
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INTERFACE_WITH_SUPERCLASS import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INTERFACE_WITH_SUPERCLASS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INVALID_TYPE_OF_ANNOTATION_MEMBER import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INVALID_TYPE_OF_ANNOTATION_MEMBER
...@@ -378,6 +380,14 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension { ...@@ -378,6 +380,14 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
FQ_NAMES_IN_TYPES, FQ_NAMES_IN_TYPES,
FQ_NAMES_IN_TYPES FQ_NAMES_IN_TYPES
) )
map.put(
GENERIC_THROWABLE_SUBCLASS,
"Subclass of 'Throwable' may not have type parameters"
)
map.put(
INNER_CLASS_OF_GENERIC_THROWABLE_SUBCLASS,
"Inner class of generic class extending 'Throwable' is prohibited"
)
// Redeclarations // Redeclarations
map.put(MANY_COMPANION_OBJECTS, "Only one companion object is allowed per class") map.put(MANY_COMPANION_OBJECTS, "Only one companion object is allowed per class")
......
...@@ -139,6 +139,8 @@ object FirErrors { ...@@ -139,6 +139,8 @@ object FirErrors {
val CATCH_PARAMETER_WITH_DEFAULT_VALUE by error0<FirSourceElement, PsiElement>() val CATCH_PARAMETER_WITH_DEFAULT_VALUE by error0<FirSourceElement, PsiElement>()
val REIFIED_TYPE_IN_CATCH_CLAUSE by error0<FirSourceElement, PsiElement>() val REIFIED_TYPE_IN_CATCH_CLAUSE by error0<FirSourceElement, PsiElement>()
val TYPE_PARAMETER_IN_CATCH_CLAUSE by error0<FirSourceElement, PsiElement>() val TYPE_PARAMETER_IN_CATCH_CLAUSE by error0<FirSourceElement, PsiElement>()
val GENERIC_THROWABLE_SUBCLASS by error0<FirSourceElement, KtTypeParameterList>()
val INNER_CLASS_OF_GENERIC_THROWABLE_SUBCLASS by error0<FirSourceElement, KtClassOrObject>(SourceElementPositioningStrategies.DECLARATION_NAME)
// Overrides // Overrides
val NOTHING_TO_OVERRIDE by error1<FirSourceElement, KtModifierListOwner, FirMemberDeclaration>(SourceElementPositioningStrategies.OVERRIDE_MODIFIER) val NOTHING_TO_OVERRIDE by error1<FirSourceElement, KtModifierListOwner, FirMemberDeclaration>(SourceElementPositioningStrategies.OVERRIDE_MODIFIER)
......
...@@ -35,6 +35,10 @@ object CommonDeclarationCheckers : DeclarationCheckers() { ...@@ -35,6 +35,10 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
FirDestructuringDeclarationChecker, FirDestructuringDeclarationChecker,
) )
override val classCheckers: Set<FirClassChecker> = setOf(
FirThrowableSubclassChecker,
)
override val regularClassCheckers: Set<FirRegularClassChecker> = setOf( override val regularClassCheckers: Set<FirRegularClassChecker> = setOf(
FirAnnotationClassDeclarationChecker, FirAnnotationClassDeclarationChecker,
FirCommonConstructorDelegationIssuesChecker, FirCommonConstructorDelegationIssuesChecker,
......
...@@ -2,11 +2,11 @@ ...@@ -2,11 +2,11 @@
// See KT-9816, KT-9742 // See KT-9816, KT-9742
// Not allowed in Java // Not allowed in Java
class ZException<T>(val p: T) : Exception() class ZException<<!GENERIC_THROWABLE_SUBCLASS!>T<!>>(val p: T) : Exception()
class YException<T>(val p: T): java.lang.RuntimeException() class YException<<!GENERIC_THROWABLE_SUBCLASS!>T<!>>(val p: T): java.lang.RuntimeException()
class XException<T>(val p: T): Throwable() class XException<<!GENERIC_THROWABLE_SUBCLASS!>T<!>>(val p: T): Throwable()
fun bar() { fun bar() {
try { try {
......
// !LANGUAGE: +ProhibitInnerClassesOfGenericClassExtendingThrowable
// !DIAGNOSTICS: -UNUSED_VARIABLE
// JAVAC_EXPECTED_FILE
class OuterGeneric<T> {
inner class ErrorInnerExn : Exception()
inner class InnerA {
inner class ErrorInnerExn2 : Exception()
}
class OkNestedExn : Exception()
val errorAnonymousObjectExn = object : Exception() {}
fun foo() {
class OkLocalExn : Exception()
val errorAnonymousObjectExn = object : Exception() {}
}
fun <X> genericFoo() {
class OkLocalExn : Exception()
class LocalGeneric<Y> {
inner class ErrorInnerExnOfLocalGeneric : Exception()
}
}
}
class Outer {
inner class InnerGeneric<T> {
inner class ErrorInnerExn : Exception()
}
}
fun <T> genericFoo() {
class ErrorLocalExnInGenericFun : Exception()
val errorkAnonymousObjectExnInGenericFun = object : Exception() {}
}
// FIR_IDENTICAL
// !LANGUAGE: +ProhibitInnerClassesOfGenericClassExtendingThrowable // !LANGUAGE: +ProhibitInnerClassesOfGenericClassExtendingThrowable
// !DIAGNOSTICS: -UNUSED_VARIABLE // !DIAGNOSTICS: -UNUSED_VARIABLE
// JAVAC_EXPECTED_FILE // JAVAC_EXPECTED_FILE
......
...@@ -3,39 +3,39 @@ ...@@ -3,39 +3,39 @@
// JAVAC_EXPECTED_FILE // JAVAC_EXPECTED_FILE
class OuterGeneric<T> { class OuterGeneric<T> {
inner class ErrorInnerExn : Exception() inner <!INNER_CLASS_OF_GENERIC_THROWABLE_SUBCLASS!>class ErrorInnerExn<!> : Exception()
inner class InnerA { inner class InnerA {
inner class ErrorInnerExn2 : Exception() inner <!INNER_CLASS_OF_GENERIC_THROWABLE_SUBCLASS!>class ErrorInnerExn2<!> : Exception()
} }
class OkNestedExn : Exception() class OkNestedExn : Exception()
val errorAnonymousObjectExn = object : Exception() {} val errorAnonymousObjectExn = <!INNER_CLASS_OF_GENERIC_THROWABLE_SUBCLASS!>object<!> : Exception() {}
fun foo() { fun foo() {
class OkLocalExn : Exception() <!INNER_CLASS_OF_GENERIC_THROWABLE_SUBCLASS!>class OkLocalExn<!> : Exception()
val errorAnonymousObjectExn = object : Exception() {} val errorAnonymousObjectExn = <!INNER_CLASS_OF_GENERIC_THROWABLE_SUBCLASS!>object<!> : Exception() {}
} }
fun <X> genericFoo() { fun <X> genericFoo() {
class OkLocalExn : Exception() <!INNER_CLASS_OF_GENERIC_THROWABLE_SUBCLASS!>class OkLocalExn<!> : Exception()
class LocalGeneric<Y> { class LocalGeneric<Y> {
inner class ErrorInnerExnOfLocalGeneric : Exception() inner <!INNER_CLASS_OF_GENERIC_THROWABLE_SUBCLASS!>class ErrorInnerExnOfLocalGeneric<!> : Exception()
} }
} }
} }
class Outer { class Outer {
inner class InnerGeneric<T> { inner class InnerGeneric<T> {
inner class ErrorInnerExn : Exception() inner <!INNER_CLASS_OF_GENERIC_THROWABLE_SUBCLASS!>class ErrorInnerExn<!> : Exception()
} }
} }
fun <T> genericFoo() { fun <T> genericFoo() {
class ErrorLocalExnInGenericFun : Exception() <!INNER_CLASS_OF_GENERIC_THROWABLE_SUBCLASS!>class ErrorLocalExnInGenericFun<!> : Exception()
val errorkAnonymousObjectExnInGenericFun = object : Exception() {} val errorkAnonymousObjectExnInGenericFun = <!INNER_CLASS_OF_GENERIC_THROWABLE_SUBCLASS!>object<!> : Exception() {}
} }
// !LANGUAGE: +ProhibitInnerClassesOfGenericClassExtendingThrowable
package test
var global: Throwable? = null
fun <T> foo(x: Throwable, z: T, b: (T) -> Unit) {
class A(val y : T) : Exception()
try {
throw x
} catch (a: A) {
b(a.y)
} catch (e: Throwable) {
global = A(z)
}
}
fun main() {
foo(RuntimeException(), 1) { throw IllegalStateException() }
foo(global!!, "") { it.length } // (*)
}
// (*):
//Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
// at test.TestKt$main$2.invoke(test.kt)
// at test.TestKt.foo(test.kt:12)
// at test.TestKt.main(test.kt:21)
\ No newline at end of file
// FIR_IDENTICAL
// !LANGUAGE: +ProhibitInnerClassesOfGenericClassExtendingThrowable // !LANGUAGE: +ProhibitInnerClassesOfGenericClassExtendingThrowable
package test package test
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册