[FIR] Implement FirNativeThrowsChecker
This commit is contained in:
+14
@@ -7,10 +7,24 @@ 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.fir.symbols.impl.FirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
|
||||
@Suppress("UNUSED_VARIABLE", "LocalVariableName", "ClassName", "unused")
|
||||
@OptIn(PrivateForInline::class)
|
||||
object NATIVE_DIAGNOSTICS_LIST : DiagnosticList("FirNativeErrors") {
|
||||
val ALL by object : DiagnosticGroup("All") {
|
||||
val THROWS_LIST_EMPTY by error<KtElement>()
|
||||
val INCOMPATIBLE_THROWS_OVERRIDE by error<KtElement> {
|
||||
parameter<FirRegularClassSymbol>("containingClass")
|
||||
}
|
||||
val INCOMPATIBLE_THROWS_INHERITED by error<KtDeclaration> {
|
||||
parameter<Collection<FirRegularClassSymbol>>("containingClasses")
|
||||
}
|
||||
val MISSING_EXCEPTION_IN_THROWS_ON_SUSPEND by error<KtElement> {
|
||||
parameter<FqName>("exceptionName")
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
@@ -8,6 +8,10 @@ package org.jetbrains.kotlin.fir.analysis.diagnostics.native
|
||||
import org.jetbrains.kotlin.diagnostics.*
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.RootDiagnosticRendererFactory
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.*
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
|
||||
/*
|
||||
* This file was generated automatically
|
||||
@@ -16,6 +20,10 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.*
|
||||
|
||||
object FirNativeErrors {
|
||||
// All
|
||||
val THROWS_LIST_EMPTY by error0<KtElement>()
|
||||
val INCOMPATIBLE_THROWS_OVERRIDE by error1<KtElement, FirRegularClassSymbol>()
|
||||
val INCOMPATIBLE_THROWS_INHERITED by error1<KtDeclaration, Collection<FirRegularClassSymbol>>()
|
||||
val MISSING_EXCEPTION_IN_THROWS_ON_SUSPEND by error1<KtElement, FqName>()
|
||||
|
||||
init {
|
||||
RootDiagnosticRendererFactory.registerFactory(FirNativeErrorsDefaultMessages)
|
||||
|
||||
+20
-2
@@ -6,8 +6,26 @@
|
||||
package org.jetbrains.kotlin.fir.analysis.diagnostics.native
|
||||
|
||||
import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactoryToRendererMap
|
||||
import org.jetbrains.kotlin.diagnostics.KtDiagnosticRenderers.TO_STRING
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.BaseDiagnosticRendererFactory
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.SYMBOL
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.SYMBOLS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.checkMissingMessages
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.native.FirNativeErrors.INCOMPATIBLE_THROWS_INHERITED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.native.FirNativeErrors.INCOMPATIBLE_THROWS_OVERRIDE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.native.FirNativeErrors.MISSING_EXCEPTION_IN_THROWS_ON_SUSPEND
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.native.FirNativeErrors.THROWS_LIST_EMPTY
|
||||
|
||||
object FirNativeErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
|
||||
override val MAP = KtDiagnosticFactoryToRendererMap("FIR")
|
||||
}
|
||||
override val MAP = KtDiagnosticFactoryToRendererMap("FIR").also { map ->
|
||||
map.put(THROWS_LIST_EMPTY, "Throws must have non-empty class list")
|
||||
map.put(INCOMPATIBLE_THROWS_OVERRIDE, "Member overrides different @Throws filter from {0}", SYMBOL)
|
||||
map.put(INCOMPATIBLE_THROWS_INHERITED, "Member inherits different @Throws filters from {0}", SYMBOLS)
|
||||
map.put(
|
||||
MISSING_EXCEPTION_IN_THROWS_ON_SUSPEND, "@Throws on suspend declaration must have {0} (or any of its superclasses) listed",
|
||||
TO_STRING
|
||||
)
|
||||
|
||||
map.checkMissingMessages(FirNativeErrors)
|
||||
}
|
||||
}
|
||||
|
||||
+184
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
* 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.analysis.native.checkers
|
||||
|
||||
import org.jetbrains.kotlin.builtins.StandardNames
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.*
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirBasicDeclarationChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.hasModifier
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.unsubstitutedScope
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.native.FirNativeErrors
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
|
||||
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||
import org.jetbrains.kotlin.fir.resolve.toFirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.scopes.getDirectOverriddenFunctions
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.classId
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.annotations.KOTLIN_THROWS_ANNOTATION_FQ_NAME
|
||||
|
||||
object FirNativeThrowsChecker : FirBasicDeclarationChecker() {
|
||||
private val throwsFqName = ClassId.topLevel(KOTLIN_THROWS_ANNOTATION_FQ_NAME)
|
||||
|
||||
private val cancellationExceptionFqName = FqName("kotlin.coroutines.cancellation.CancellationException")
|
||||
|
||||
private val cancellationExceptionAndSupersClassIds = setOf(
|
||||
ClassId.topLevel(StandardNames.FqNames.throwable),
|
||||
ClassId.topLevel(FqName("kotlin.Exception")),
|
||||
ClassId.topLevel(FqName("kotlin.RuntimeException")),
|
||||
ClassId.topLevel(FqName("kotlin.IllegalStateException")),
|
||||
ClassId.topLevel(cancellationExceptionFqName)
|
||||
)
|
||||
|
||||
override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
val throwsAnnotation = declaration.getAnnotationByClassId(throwsFqName) as? FirAnnotationCall
|
||||
|
||||
if (!checkInheritance(declaration, throwsAnnotation, context, reporter)) return
|
||||
|
||||
if (throwsAnnotation.hasUnresolvedArgument()) return
|
||||
|
||||
val classTypes = throwsAnnotation?.getClassTypes(context.session) ?: return
|
||||
|
||||
if (classTypes.isEmpty()) {
|
||||
reporter.reportOn(throwsAnnotation.source, FirNativeErrors.THROWS_LIST_EMPTY, context)
|
||||
return
|
||||
}
|
||||
|
||||
if (declaration.hasModifier(KtTokens.SUSPEND_KEYWORD) && classTypes.none { it.classId in cancellationExceptionAndSupersClassIds }) {
|
||||
reporter.reportOn(
|
||||
throwsAnnotation.source,
|
||||
FirNativeErrors.MISSING_EXCEPTION_IN_THROWS_ON_SUSPEND,
|
||||
cancellationExceptionFqName,
|
||||
context
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkInheritance(
|
||||
declaration: FirDeclaration,
|
||||
throwsAnnotation: FirAnnotationCall?,
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter
|
||||
): Boolean {
|
||||
if (declaration !is FirSimpleFunction) return true
|
||||
|
||||
val inherited = getInheritedThrows(declaration, throwsAnnotation, context).entries.distinctBy { it.value }
|
||||
|
||||
if (inherited.size >= 2) {
|
||||
reporter.reportOn(
|
||||
declaration.source,
|
||||
FirNativeErrors.INCOMPATIBLE_THROWS_INHERITED,
|
||||
inherited.mapNotNull { it.key.containingClass()?.toFirRegularClassSymbol(context.session) },
|
||||
context
|
||||
)
|
||||
return false
|
||||
}
|
||||
|
||||
val (overriddenMember, overriddenThrows) = inherited.firstOrNull()
|
||||
?: return true // Should not happen though.
|
||||
|
||||
if (decodeThrowsFilter(throwsAnnotation, context.session) != overriddenThrows) {
|
||||
val containingClassSymbol = overriddenMember.containingClass()?.toFirRegularClassSymbol(context.session)
|
||||
if (containingClassSymbol != null) {
|
||||
reporter.reportOn(throwsAnnotation?.source, FirNativeErrors.INCOMPATIBLE_THROWS_OVERRIDE, containingClassSymbol, context)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private fun getInheritedThrows(
|
||||
function: FirSimpleFunction,
|
||||
throwsAnnotation: FirAnnotationCall?,
|
||||
context: CheckerContext
|
||||
): Map<FirNamedFunctionSymbol, ThrowsFilter> {
|
||||
val visited = mutableSetOf<FirNamedFunctionSymbol>()
|
||||
val result = mutableMapOf<FirNamedFunctionSymbol, ThrowsFilter>()
|
||||
|
||||
fun getInheritedThrows(localThrowsAnnotation: FirAnnotationCall?, localFunctionSymbol: FirNamedFunctionSymbol) {
|
||||
if (!visited.add(localFunctionSymbol)) return
|
||||
val containingClassSymbol = localFunctionSymbol.containingClass()?.toFirRegularClassSymbol(context.session)
|
||||
|
||||
if (containingClassSymbol != null) {
|
||||
val unsubstitutedScope = containingClassSymbol.unsubstitutedScope(context)
|
||||
unsubstitutedScope.processFunctionsByName(localFunctionSymbol.name) {}
|
||||
val overriddenFunctions = unsubstitutedScope.getDirectOverriddenFunctions(localFunctionSymbol)
|
||||
if (localFunctionSymbol == function.symbol || localThrowsAnnotation == null && overriddenFunctions.isNotEmpty()) {
|
||||
for (overriddenFunction in overriddenFunctions) {
|
||||
val annotation = if (overriddenFunction.isSubstitutionOrIntersectionOverride) {
|
||||
null
|
||||
} else {
|
||||
overriddenFunction.getAnnotationByClassId(throwsFqName) as? FirAnnotationCall
|
||||
}
|
||||
getInheritedThrows(annotation, overriddenFunction)
|
||||
}
|
||||
} else {
|
||||
result[localFunctionSymbol] = decodeThrowsFilter(localThrowsAnnotation, context.session)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getInheritedThrows(throwsAnnotation, function.symbol)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private fun FirElement?.hasUnresolvedArgument(): Boolean {
|
||||
if (this is FirWrappedArgumentExpression) {
|
||||
return expression.hasUnresolvedArgument()
|
||||
}
|
||||
|
||||
if (this is FirResolvable) {
|
||||
if (this.calleeReference is FirErrorNamedReference) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
if (this is FirVarargArgumentsExpression) {
|
||||
for (argument in this.arguments) {
|
||||
if (argument.hasUnresolvedArgument()) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this is FirCall) {
|
||||
for (argument in this.argumentList.arguments) {
|
||||
if (argument.hasUnresolvedArgument()) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
private fun decodeThrowsFilter(throwsAnnotation: FirAnnotationCall?, session: FirSession): ThrowsFilter {
|
||||
return ThrowsFilter(throwsAnnotation?.getClassTypes(session)?.toSet())
|
||||
}
|
||||
|
||||
private fun FirAnnotationCall.getClassTypes(session: FirSession): List<ConeKotlinType> {
|
||||
val arguments = argumentList.arguments
|
||||
return (arguments.firstOrNull() as? FirVarargArgumentsExpression)?.arguments
|
||||
?.filterIsInstance<FirGetClassCall>()
|
||||
?.map { it.arguments.first().typeRef }
|
||||
?.filterIsInstance<FirResolvedTypeRef>()
|
||||
?.map { it.type.fullyExpandedType(session) }
|
||||
?: emptyList()
|
||||
}
|
||||
|
||||
private data class ThrowsFilter(val classes: Set<ConeKotlinType>?)
|
||||
}
|
||||
+5
@@ -6,6 +6,11 @@
|
||||
package org.jetbrains.kotlin.fir.analysis.native.checkers
|
||||
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.DeclarationCheckers
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirBasicDeclarationChecker
|
||||
|
||||
object NativeDeclarationCheckers : DeclarationCheckers() {
|
||||
override val basicDeclarationCheckers: Set<FirBasicDeclarationChecker>
|
||||
get() = setOf(
|
||||
FirNativeThrowsChecker
|
||||
)
|
||||
}
|
||||
+40
-40
@@ -31,10 +31,10 @@ class Exception1 : Throwable()
|
||||
class Exception2 : Throwable()
|
||||
class Exception3 : Throwable()
|
||||
|
||||
@Throws
|
||||
<!THROWS_LIST_EMPTY!>@Throws<!>
|
||||
fun foo() {}
|
||||
|
||||
@Throws()
|
||||
<!THROWS_LIST_EMPTY!>@Throws()<!>
|
||||
fun throwsEmptyParens() {}
|
||||
|
||||
@Throws(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!><!UNRESOLVED_REFERENCE!>UnresolvedException<!>::class<!>)
|
||||
@@ -43,16 +43,16 @@ fun throwsUnresolved() {}
|
||||
@Throws(exceptionClasses = <!ANNOTATION_ARGUMENT_MUST_BE_CONST, ARGUMENT_TYPE_MISMATCH, ASSIGNING_SINGLE_ELEMENT_TO_VARARG_IN_NAMED_FORM_ANNOTATION_ERROR!><!UNRESOLVED_REFERENCE!>UnresolvedException<!>::class<!>)
|
||||
fun throwsNamedUnresolved() {}
|
||||
|
||||
@Throws(exceptionClasses = [])
|
||||
<!THROWS_LIST_EMPTY!>@Throws(exceptionClasses = [])<!>
|
||||
fun throwsNamedEmptyLiteral() {}
|
||||
|
||||
@Throws(exceptionClasses = arrayOf())
|
||||
<!THROWS_LIST_EMPTY!>@Throws(exceptionClasses = arrayOf())<!>
|
||||
fun throwsNamedEmptyArrayOf() {}
|
||||
|
||||
@Throws(*[])
|
||||
<!THROWS_LIST_EMPTY!>@Throws(*[])<!>
|
||||
fun throwsSpreadEmptyLiteral() {}
|
||||
|
||||
@Throws(*arrayOf())
|
||||
<!THROWS_LIST_EMPTY!>@Throws(*arrayOf())<!>
|
||||
fun throwsSpreadEmptyArrayOf() {}
|
||||
|
||||
@Throws(exceptionClasses = <!NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION!>[<!ANNOTATION_ARGUMENT_MUST_BE_CONST!><!UNRESOLVED_REFERENCE!>UE<!>::class<!>]<!>)
|
||||
@@ -77,7 +77,7 @@ interface Base0 {
|
||||
}
|
||||
|
||||
class ThrowsOnOverride : Base0 {
|
||||
@Throws(Exception1::class) override fun foo() {}
|
||||
<!INCOMPATIBLE_THROWS_OVERRIDE!>@Throws(Exception1::class)<!> override fun foo() {}
|
||||
}
|
||||
|
||||
interface Base1 {
|
||||
@@ -85,11 +85,11 @@ interface Base1 {
|
||||
}
|
||||
|
||||
class InheritsThrowsAndNoThrows : Base0, Base1 {
|
||||
override fun foo() {}
|
||||
<!INCOMPATIBLE_THROWS_INHERITED!>override fun foo() {}<!>
|
||||
}
|
||||
|
||||
class OverridesThrowsAndNoThrows : Base0, Base1 {
|
||||
@Throws(Exception1::class) override fun foo() {}
|
||||
<!INCOMPATIBLE_THROWS_INHERITED!>@Throws(Exception1::class) override fun foo() {}<!>
|
||||
}
|
||||
|
||||
class SameThrowsOnOverride : Base1 {
|
||||
@@ -97,11 +97,11 @@ class SameThrowsOnOverride : Base1 {
|
||||
}
|
||||
|
||||
class DifferentThrowsOnOverride : Base1 {
|
||||
@Throws(Exception2::class) override fun foo() {}
|
||||
<!INCOMPATIBLE_THROWS_OVERRIDE!>@Throws(Exception2::class)<!> override fun foo() {}
|
||||
}
|
||||
|
||||
class HasThrowsWithEmptyListOnOverride : Base1 {
|
||||
@Throws override fun foo() {}
|
||||
<!INCOMPATIBLE_THROWS_OVERRIDE!>@Throws<!> override fun foo() {}
|
||||
}
|
||||
|
||||
interface Base2 {
|
||||
@@ -109,31 +109,31 @@ interface Base2 {
|
||||
}
|
||||
|
||||
open class InheritsDifferentThrows1 : Base1, Base2 {
|
||||
override fun foo() {}
|
||||
<!INCOMPATIBLE_THROWS_INHERITED!>override fun foo() {}<!>
|
||||
}
|
||||
|
||||
open class OverridesDifferentThrows1_1 : Base1, Base2 {
|
||||
@Throws(Exception1::class) override fun foo() {}
|
||||
<!INCOMPATIBLE_THROWS_INHERITED!>@Throws(Exception1::class) override fun foo() {}<!>
|
||||
}
|
||||
|
||||
open class OverridesDifferentThrows1_2 : Base1, Base2 {
|
||||
@Throws(Exception2::class) override fun foo() {}
|
||||
<!INCOMPATIBLE_THROWS_INHERITED!>@Throws(Exception2::class) override fun foo() {}<!>
|
||||
}
|
||||
|
||||
open class OverridesDifferentThrows1_3 : Base1, Base2 {
|
||||
@Throws(Exception1::class, Exception2::class) override fun foo() {}
|
||||
<!INCOMPATIBLE_THROWS_INHERITED!>@Throws(Exception1::class, Exception2::class) override fun foo() {}<!>
|
||||
}
|
||||
|
||||
class InheritsDifferentThrowsThroughSameClass1 : InheritsDifferentThrows1() {
|
||||
override fun foo() {}
|
||||
<!INCOMPATIBLE_THROWS_INHERITED!>override fun foo() {}<!>
|
||||
}
|
||||
|
||||
class OverridesDifferentThrowsThroughSameClass1 : InheritsDifferentThrows1() {
|
||||
@Throws(Exception1::class) override fun foo() {}
|
||||
<!INCOMPATIBLE_THROWS_INHERITED!>@Throws(Exception1::class) override fun foo() {}<!>
|
||||
}
|
||||
|
||||
class OverridesDifferentThrowsThroughSameClass2 : InheritsDifferentThrows1() {
|
||||
@Throws(Exception2::class) override fun foo() {}
|
||||
<!INCOMPATIBLE_THROWS_INHERITED!>@Throws(Exception2::class) override fun foo() {}<!>
|
||||
}
|
||||
|
||||
interface Base3 {
|
||||
@@ -141,15 +141,15 @@ interface Base3 {
|
||||
}
|
||||
|
||||
class InheritsDifferentThrows2 : InheritsDifferentThrows1(), Base3 {
|
||||
override fun foo() {}
|
||||
<!INCOMPATIBLE_THROWS_INHERITED!>override fun foo() {}<!>
|
||||
}
|
||||
|
||||
class OverridesDifferentThrows2 : InheritsDifferentThrows1(), Base3 {
|
||||
@Throws(Exception3::class) override fun foo() {}
|
||||
<!INCOMPATIBLE_THROWS_INHERITED!>@Throws(Exception3::class) override fun foo() {}<!>
|
||||
}
|
||||
|
||||
open class OverridesDifferentThrows3 : Base1, Base2 {
|
||||
@Throws(Exception3::class) override fun foo() {}
|
||||
<!INCOMPATIBLE_THROWS_INHERITED!>@Throws(Exception3::class) override fun foo() {}<!>
|
||||
}
|
||||
|
||||
class InheritsDifferentThrows3 : OverridesDifferentThrows3() {
|
||||
@@ -165,7 +165,7 @@ class OverrideDifferentThrows5 : OverridesDifferentThrows3() {
|
||||
}
|
||||
|
||||
class OverrideDifferentThrows6 : OverridesDifferentThrows3() {
|
||||
@Throws(Exception1::class) override fun foo() {}
|
||||
<!INCOMPATIBLE_THROWS_OVERRIDE!>@Throws(Exception1::class)<!> override fun foo() {}
|
||||
}
|
||||
|
||||
interface Base4 {
|
||||
@@ -181,11 +181,11 @@ class OverridesSameThrows : Base1, Base4 {
|
||||
}
|
||||
|
||||
class OverrideDifferentThrows7 : Base1, Base4 {
|
||||
@Throws(Exception2::class) override fun foo() {}
|
||||
<!INCOMPATIBLE_THROWS_OVERRIDE!>@Throws(Exception2::class)<!> override fun foo() {}
|
||||
}
|
||||
|
||||
class OverrideDifferentThrows8 : Base1, Base3 {
|
||||
@Throws(Exception2::class) override fun foo() {}
|
||||
<!INCOMPATIBLE_THROWS_INHERITED!>@Throws(Exception2::class) override fun foo() {}<!>
|
||||
}
|
||||
|
||||
interface Base5 {
|
||||
@@ -209,7 +209,7 @@ class OverridesSameThrowsMultiple2 : Base5, Base6 {
|
||||
}
|
||||
|
||||
class OverridesDifferentThrowsMultiple : Base5, Base6 {
|
||||
@Throws(Exception1::class) override fun foo() {}
|
||||
<!INCOMPATIBLE_THROWS_OVERRIDE!>@Throws(Exception1::class)<!> override fun foo() {}
|
||||
}
|
||||
|
||||
fun withLocalClass() {
|
||||
@@ -220,11 +220,11 @@ fun withLocalClass() {
|
||||
}
|
||||
|
||||
class InheritsDifferentThrowsLocal : Base1, Base7() {
|
||||
override fun foo() {}
|
||||
<!INCOMPATIBLE_THROWS_INHERITED!>override fun foo() {}<!>
|
||||
}
|
||||
|
||||
class OverridesDifferentThrowsLocal : Base1, Base7() {
|
||||
@Throws(Exception1::class, LocalException::class) override fun foo() {}
|
||||
<!INCOMPATIBLE_THROWS_INHERITED!>@Throws(Exception1::class, LocalException::class) override fun foo() {}<!>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,24 +235,24 @@ class InheritThrowsOnFakeOverride : ThrowsOnFakeOverride {
|
||||
}
|
||||
|
||||
class OverrideDifferentThrowsOnFakeOverride : ThrowsOnFakeOverride {
|
||||
@Throws(Exception2::class) override fun foo() {}
|
||||
<!INCOMPATIBLE_THROWS_OVERRIDE!>@Throws(Exception2::class)<!> override fun foo() {}
|
||||
}
|
||||
|
||||
interface IncompatibleThrowsOnFakeOverride : Base1, Base2
|
||||
|
||||
class OverrideIncompatibleThrowsOnFakeOverride1 : IncompatibleThrowsOnFakeOverride {
|
||||
@Throws(Exception1::class) override fun foo() {}
|
||||
<!INCOMPATIBLE_THROWS_INHERITED!>@Throws(Exception1::class) override fun foo() {}<!>
|
||||
}
|
||||
|
||||
class OverrideIncompatibleThrowsOnFakeOverride2 : IncompatibleThrowsOnFakeOverride {
|
||||
@Throws(Exception2::class) override fun foo() {}
|
||||
<!INCOMPATIBLE_THROWS_INHERITED!>@Throws(Exception2::class) override fun foo() {}<!>
|
||||
}
|
||||
|
||||
class InheritIncompatibleThrowsOnFakeOverride : IncompatibleThrowsOnFakeOverride {
|
||||
override fun foo() {}
|
||||
<!INCOMPATIBLE_THROWS_INHERITED!>override fun foo() {}<!>
|
||||
}
|
||||
|
||||
@Throws
|
||||
<!THROWS_LIST_EMPTY!>@Throws<!>
|
||||
suspend fun suspendThrowsNothing() {}
|
||||
|
||||
interface SuspendFun {
|
||||
@@ -262,7 +262,7 @@ interface SuspendFun {
|
||||
class OverrideImplicitThrowsOnSuspendWithExplicit : SuspendFun {
|
||||
// Although `SuspendFun.foo` effectively has `@Throws(CancellationException::class)`,
|
||||
// overriding it with equal explicit `@Throws` is forbidden:
|
||||
@Throws(CancellationException::class) override suspend fun foo() {}
|
||||
<!INCOMPATIBLE_THROWS_OVERRIDE!>@Throws(CancellationException::class)<!> override suspend fun foo() {}
|
||||
}
|
||||
|
||||
interface SuspendFunThrows {
|
||||
@@ -273,10 +273,10 @@ class InheritExplicitThrowsOnSuspend : SuspendFunThrows {
|
||||
override suspend fun foo() {}
|
||||
}
|
||||
|
||||
@Throws(Exception1::class)
|
||||
<!MISSING_EXCEPTION_IN_THROWS_ON_SUSPEND!>@Throws(Exception1::class)<!>
|
||||
suspend fun suspendDoesNotThrowCancellationException1() {}
|
||||
|
||||
@Throws(Exception1::class, Exception2::class)
|
||||
<!MISSING_EXCEPTION_IN_THROWS_ON_SUSPEND!>@Throws(Exception1::class, Exception2::class)<!>
|
||||
suspend fun suspendDoesNotThrowCancellationException2() {}
|
||||
|
||||
@Throws(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!><!UNRESOLVED_REFERENCE!>UE<!>::class<!>)
|
||||
@@ -285,16 +285,16 @@ suspend fun suspendThrowsUnresolved() {}
|
||||
@Throws(exceptionClasses = <!ANNOTATION_ARGUMENT_MUST_BE_CONST, ARGUMENT_TYPE_MISMATCH, ASSIGNING_SINGLE_ELEMENT_TO_VARARG_IN_NAMED_FORM_ANNOTATION_ERROR!><!UNRESOLVED_REFERENCE!>UE<!>::class<!>)
|
||||
suspend fun suspendThrowsNamedUnresolved() {}
|
||||
|
||||
@Throws(exceptionClasses = [])
|
||||
<!THROWS_LIST_EMPTY!>@Throws(exceptionClasses = [])<!>
|
||||
suspend fun suspendThrowsNamedEmptyLiteral() {}
|
||||
|
||||
@Throws(exceptionClasses = arrayOf())
|
||||
<!THROWS_LIST_EMPTY!>@Throws(exceptionClasses = arrayOf())<!>
|
||||
suspend fun suspendThrowsNamedEmptyArrayOf() {}
|
||||
|
||||
@Throws(*[])
|
||||
<!THROWS_LIST_EMPTY!>@Throws(*[])<!>
|
||||
suspend fun suspendThrowsSpreadEmptyLiteral() {}
|
||||
|
||||
@Throws(*arrayOf())
|
||||
<!THROWS_LIST_EMPTY!>@Throws(*arrayOf())<!>
|
||||
suspend fun suspendThrowsSpreadEmptyArrayOf() {}
|
||||
|
||||
@Throws(exceptionClasses = <!NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION!>[<!ANNOTATION_ARGUMENT_MUST_BE_CONST!><!UNRESOLVED_REFERENCE!>UE<!>::class<!>]<!>)
|
||||
@@ -309,7 +309,7 @@ suspend fun suspendThrowsSpreadLiteralWithUnresolved() {}
|
||||
@Throws(*<!NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION!>arrayOf(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!><!UNRESOLVED_REFERENCE!>UE<!>::class<!>)<!>)
|
||||
suspend fun suspendThrowsSpreadArrayOfUnresolved() {}
|
||||
|
||||
@Throws(UEAlias::class)
|
||||
<!MISSING_EXCEPTION_IN_THROWS_ON_SUSPEND!>@Throws(UEAlias::class)<!>
|
||||
suspend fun suspendThrowsTypealiasToUnresolved() {}
|
||||
|
||||
@Throws(Exception1::class, CancellationException::class)
|
||||
|
||||
Reference in New Issue
Block a user