[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.PrivateForInline
|
||||||
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.DiagnosticList
|
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")
|
@Suppress("UNUSED_VARIABLE", "LocalVariableName", "ClassName", "unused")
|
||||||
@OptIn(PrivateForInline::class)
|
@OptIn(PrivateForInline::class)
|
||||||
object NATIVE_DIAGNOSTICS_LIST : DiagnosticList("FirNativeErrors") {
|
object NATIVE_DIAGNOSTICS_LIST : DiagnosticList("FirNativeErrors") {
|
||||||
val ALL by object : DiagnosticGroup("All") {
|
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.*
|
||||||
import org.jetbrains.kotlin.diagnostics.rendering.RootDiagnosticRendererFactory
|
import org.jetbrains.kotlin.diagnostics.rendering.RootDiagnosticRendererFactory
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.*
|
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
|
* This file was generated automatically
|
||||||
@@ -16,6 +20,10 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.*
|
|||||||
|
|
||||||
object FirNativeErrors {
|
object FirNativeErrors {
|
||||||
// All
|
// 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 {
|
init {
|
||||||
RootDiagnosticRendererFactory.registerFactory(FirNativeErrorsDefaultMessages)
|
RootDiagnosticRendererFactory.registerFactory(FirNativeErrorsDefaultMessages)
|
||||||
|
|||||||
+20
-2
@@ -6,8 +6,26 @@
|
|||||||
package org.jetbrains.kotlin.fir.analysis.diagnostics.native
|
package org.jetbrains.kotlin.fir.analysis.diagnostics.native
|
||||||
|
|
||||||
import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactoryToRendererMap
|
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.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() {
|
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
|
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.DeclarationCheckers
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirBasicDeclarationChecker
|
||||||
|
|
||||||
object NativeDeclarationCheckers : DeclarationCheckers() {
|
object NativeDeclarationCheckers : DeclarationCheckers() {
|
||||||
|
override val basicDeclarationCheckers: Set<FirBasicDeclarationChecker>
|
||||||
|
get() = setOf(
|
||||||
|
FirNativeThrowsChecker
|
||||||
|
)
|
||||||
}
|
}
|
||||||
+40
-40
@@ -31,10 +31,10 @@ class Exception1 : Throwable()
|
|||||||
class Exception2 : Throwable()
|
class Exception2 : Throwable()
|
||||||
class Exception3 : Throwable()
|
class Exception3 : Throwable()
|
||||||
|
|
||||||
@Throws
|
<!THROWS_LIST_EMPTY!>@Throws<!>
|
||||||
fun foo() {}
|
fun foo() {}
|
||||||
|
|
||||||
@Throws()
|
<!THROWS_LIST_EMPTY!>@Throws()<!>
|
||||||
fun throwsEmptyParens() {}
|
fun throwsEmptyParens() {}
|
||||||
|
|
||||||
@Throws(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!><!UNRESOLVED_REFERENCE!>UnresolvedException<!>::class<!>)
|
@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<!>)
|
@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() {}
|
fun throwsNamedUnresolved() {}
|
||||||
|
|
||||||
@Throws(exceptionClasses = [])
|
<!THROWS_LIST_EMPTY!>@Throws(exceptionClasses = [])<!>
|
||||||
fun throwsNamedEmptyLiteral() {}
|
fun throwsNamedEmptyLiteral() {}
|
||||||
|
|
||||||
@Throws(exceptionClasses = arrayOf())
|
<!THROWS_LIST_EMPTY!>@Throws(exceptionClasses = arrayOf())<!>
|
||||||
fun throwsNamedEmptyArrayOf() {}
|
fun throwsNamedEmptyArrayOf() {}
|
||||||
|
|
||||||
@Throws(*[])
|
<!THROWS_LIST_EMPTY!>@Throws(*[])<!>
|
||||||
fun throwsSpreadEmptyLiteral() {}
|
fun throwsSpreadEmptyLiteral() {}
|
||||||
|
|
||||||
@Throws(*arrayOf())
|
<!THROWS_LIST_EMPTY!>@Throws(*arrayOf())<!>
|
||||||
fun throwsSpreadEmptyArrayOf() {}
|
fun throwsSpreadEmptyArrayOf() {}
|
||||||
|
|
||||||
@Throws(exceptionClasses = <!NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION!>[<!ANNOTATION_ARGUMENT_MUST_BE_CONST!><!UNRESOLVED_REFERENCE!>UE<!>::class<!>]<!>)
|
@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 {
|
class ThrowsOnOverride : Base0 {
|
||||||
@Throws(Exception1::class) override fun foo() {}
|
<!INCOMPATIBLE_THROWS_OVERRIDE!>@Throws(Exception1::class)<!> override fun foo() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Base1 {
|
interface Base1 {
|
||||||
@@ -85,11 +85,11 @@ interface Base1 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class InheritsThrowsAndNoThrows : Base0, Base1 {
|
class InheritsThrowsAndNoThrows : Base0, Base1 {
|
||||||
override fun foo() {}
|
<!INCOMPATIBLE_THROWS_INHERITED!>override fun foo() {}<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
class OverridesThrowsAndNoThrows : Base0, Base1 {
|
class OverridesThrowsAndNoThrows : Base0, Base1 {
|
||||||
@Throws(Exception1::class) override fun foo() {}
|
<!INCOMPATIBLE_THROWS_INHERITED!>@Throws(Exception1::class) override fun foo() {}<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
class SameThrowsOnOverride : Base1 {
|
class SameThrowsOnOverride : Base1 {
|
||||||
@@ -97,11 +97,11 @@ class SameThrowsOnOverride : Base1 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class DifferentThrowsOnOverride : Base1 {
|
class DifferentThrowsOnOverride : Base1 {
|
||||||
@Throws(Exception2::class) override fun foo() {}
|
<!INCOMPATIBLE_THROWS_OVERRIDE!>@Throws(Exception2::class)<!> override fun foo() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
class HasThrowsWithEmptyListOnOverride : Base1 {
|
class HasThrowsWithEmptyListOnOverride : Base1 {
|
||||||
@Throws override fun foo() {}
|
<!INCOMPATIBLE_THROWS_OVERRIDE!>@Throws<!> override fun foo() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Base2 {
|
interface Base2 {
|
||||||
@@ -109,31 +109,31 @@ interface Base2 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
open class InheritsDifferentThrows1 : Base1, Base2 {
|
open class InheritsDifferentThrows1 : Base1, Base2 {
|
||||||
override fun foo() {}
|
<!INCOMPATIBLE_THROWS_INHERITED!>override fun foo() {}<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
open class OverridesDifferentThrows1_1 : Base1, Base2 {
|
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 {
|
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 {
|
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() {
|
class InheritsDifferentThrowsThroughSameClass1 : InheritsDifferentThrows1() {
|
||||||
override fun foo() {}
|
<!INCOMPATIBLE_THROWS_INHERITED!>override fun foo() {}<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
class OverridesDifferentThrowsThroughSameClass1 : InheritsDifferentThrows1() {
|
class OverridesDifferentThrowsThroughSameClass1 : InheritsDifferentThrows1() {
|
||||||
@Throws(Exception1::class) override fun foo() {}
|
<!INCOMPATIBLE_THROWS_INHERITED!>@Throws(Exception1::class) override fun foo() {}<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
class OverridesDifferentThrowsThroughSameClass2 : InheritsDifferentThrows1() {
|
class OverridesDifferentThrowsThroughSameClass2 : InheritsDifferentThrows1() {
|
||||||
@Throws(Exception2::class) override fun foo() {}
|
<!INCOMPATIBLE_THROWS_INHERITED!>@Throws(Exception2::class) override fun foo() {}<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Base3 {
|
interface Base3 {
|
||||||
@@ -141,15 +141,15 @@ interface Base3 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class InheritsDifferentThrows2 : InheritsDifferentThrows1(), Base3 {
|
class InheritsDifferentThrows2 : InheritsDifferentThrows1(), Base3 {
|
||||||
override fun foo() {}
|
<!INCOMPATIBLE_THROWS_INHERITED!>override fun foo() {}<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
class OverridesDifferentThrows2 : InheritsDifferentThrows1(), Base3 {
|
class OverridesDifferentThrows2 : InheritsDifferentThrows1(), Base3 {
|
||||||
@Throws(Exception3::class) override fun foo() {}
|
<!INCOMPATIBLE_THROWS_INHERITED!>@Throws(Exception3::class) override fun foo() {}<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
open class OverridesDifferentThrows3 : Base1, Base2 {
|
open class OverridesDifferentThrows3 : Base1, Base2 {
|
||||||
@Throws(Exception3::class) override fun foo() {}
|
<!INCOMPATIBLE_THROWS_INHERITED!>@Throws(Exception3::class) override fun foo() {}<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
class InheritsDifferentThrows3 : OverridesDifferentThrows3() {
|
class InheritsDifferentThrows3 : OverridesDifferentThrows3() {
|
||||||
@@ -165,7 +165,7 @@ class OverrideDifferentThrows5 : OverridesDifferentThrows3() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class OverrideDifferentThrows6 : OverridesDifferentThrows3() {
|
class OverrideDifferentThrows6 : OverridesDifferentThrows3() {
|
||||||
@Throws(Exception1::class) override fun foo() {}
|
<!INCOMPATIBLE_THROWS_OVERRIDE!>@Throws(Exception1::class)<!> override fun foo() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Base4 {
|
interface Base4 {
|
||||||
@@ -181,11 +181,11 @@ class OverridesSameThrows : Base1, Base4 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class OverrideDifferentThrows7 : 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 {
|
class OverrideDifferentThrows8 : Base1, Base3 {
|
||||||
@Throws(Exception2::class) override fun foo() {}
|
<!INCOMPATIBLE_THROWS_INHERITED!>@Throws(Exception2::class) override fun foo() {}<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Base5 {
|
interface Base5 {
|
||||||
@@ -209,7 +209,7 @@ class OverridesSameThrowsMultiple2 : Base5, Base6 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class OverridesDifferentThrowsMultiple : Base5, Base6 {
|
class OverridesDifferentThrowsMultiple : Base5, Base6 {
|
||||||
@Throws(Exception1::class) override fun foo() {}
|
<!INCOMPATIBLE_THROWS_OVERRIDE!>@Throws(Exception1::class)<!> override fun foo() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun withLocalClass() {
|
fun withLocalClass() {
|
||||||
@@ -220,11 +220,11 @@ fun withLocalClass() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class InheritsDifferentThrowsLocal : Base1, Base7() {
|
class InheritsDifferentThrowsLocal : Base1, Base7() {
|
||||||
override fun foo() {}
|
<!INCOMPATIBLE_THROWS_INHERITED!>override fun foo() {}<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
class OverridesDifferentThrowsLocal : Base1, Base7() {
|
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 {
|
class OverrideDifferentThrowsOnFakeOverride : ThrowsOnFakeOverride {
|
||||||
@Throws(Exception2::class) override fun foo() {}
|
<!INCOMPATIBLE_THROWS_OVERRIDE!>@Throws(Exception2::class)<!> override fun foo() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IncompatibleThrowsOnFakeOverride : Base1, Base2
|
interface IncompatibleThrowsOnFakeOverride : Base1, Base2
|
||||||
|
|
||||||
class OverrideIncompatibleThrowsOnFakeOverride1 : IncompatibleThrowsOnFakeOverride {
|
class OverrideIncompatibleThrowsOnFakeOverride1 : IncompatibleThrowsOnFakeOverride {
|
||||||
@Throws(Exception1::class) override fun foo() {}
|
<!INCOMPATIBLE_THROWS_INHERITED!>@Throws(Exception1::class) override fun foo() {}<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
class OverrideIncompatibleThrowsOnFakeOverride2 : IncompatibleThrowsOnFakeOverride {
|
class OverrideIncompatibleThrowsOnFakeOverride2 : IncompatibleThrowsOnFakeOverride {
|
||||||
@Throws(Exception2::class) override fun foo() {}
|
<!INCOMPATIBLE_THROWS_INHERITED!>@Throws(Exception2::class) override fun foo() {}<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
class InheritIncompatibleThrowsOnFakeOverride : IncompatibleThrowsOnFakeOverride {
|
class InheritIncompatibleThrowsOnFakeOverride : IncompatibleThrowsOnFakeOverride {
|
||||||
override fun foo() {}
|
<!INCOMPATIBLE_THROWS_INHERITED!>override fun foo() {}<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws
|
<!THROWS_LIST_EMPTY!>@Throws<!>
|
||||||
suspend fun suspendThrowsNothing() {}
|
suspend fun suspendThrowsNothing() {}
|
||||||
|
|
||||||
interface SuspendFun {
|
interface SuspendFun {
|
||||||
@@ -262,7 +262,7 @@ interface SuspendFun {
|
|||||||
class OverrideImplicitThrowsOnSuspendWithExplicit : SuspendFun {
|
class OverrideImplicitThrowsOnSuspendWithExplicit : SuspendFun {
|
||||||
// Although `SuspendFun.foo` effectively has `@Throws(CancellationException::class)`,
|
// Although `SuspendFun.foo` effectively has `@Throws(CancellationException::class)`,
|
||||||
// overriding it with equal explicit `@Throws` is forbidden:
|
// 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 {
|
interface SuspendFunThrows {
|
||||||
@@ -273,10 +273,10 @@ class InheritExplicitThrowsOnSuspend : SuspendFunThrows {
|
|||||||
override suspend fun foo() {}
|
override suspend fun foo() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(Exception1::class)
|
<!MISSING_EXCEPTION_IN_THROWS_ON_SUSPEND!>@Throws(Exception1::class)<!>
|
||||||
suspend fun suspendDoesNotThrowCancellationException1() {}
|
suspend fun suspendDoesNotThrowCancellationException1() {}
|
||||||
|
|
||||||
@Throws(Exception1::class, Exception2::class)
|
<!MISSING_EXCEPTION_IN_THROWS_ON_SUSPEND!>@Throws(Exception1::class, Exception2::class)<!>
|
||||||
suspend fun suspendDoesNotThrowCancellationException2() {}
|
suspend fun suspendDoesNotThrowCancellationException2() {}
|
||||||
|
|
||||||
@Throws(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!><!UNRESOLVED_REFERENCE!>UE<!>::class<!>)
|
@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<!>)
|
@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() {}
|
suspend fun suspendThrowsNamedUnresolved() {}
|
||||||
|
|
||||||
@Throws(exceptionClasses = [])
|
<!THROWS_LIST_EMPTY!>@Throws(exceptionClasses = [])<!>
|
||||||
suspend fun suspendThrowsNamedEmptyLiteral() {}
|
suspend fun suspendThrowsNamedEmptyLiteral() {}
|
||||||
|
|
||||||
@Throws(exceptionClasses = arrayOf())
|
<!THROWS_LIST_EMPTY!>@Throws(exceptionClasses = arrayOf())<!>
|
||||||
suspend fun suspendThrowsNamedEmptyArrayOf() {}
|
suspend fun suspendThrowsNamedEmptyArrayOf() {}
|
||||||
|
|
||||||
@Throws(*[])
|
<!THROWS_LIST_EMPTY!>@Throws(*[])<!>
|
||||||
suspend fun suspendThrowsSpreadEmptyLiteral() {}
|
suspend fun suspendThrowsSpreadEmptyLiteral() {}
|
||||||
|
|
||||||
@Throws(*arrayOf())
|
<!THROWS_LIST_EMPTY!>@Throws(*arrayOf())<!>
|
||||||
suspend fun suspendThrowsSpreadEmptyArrayOf() {}
|
suspend fun suspendThrowsSpreadEmptyArrayOf() {}
|
||||||
|
|
||||||
@Throws(exceptionClasses = <!NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION!>[<!ANNOTATION_ARGUMENT_MUST_BE_CONST!><!UNRESOLVED_REFERENCE!>UE<!>::class<!>]<!>)
|
@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<!>)<!>)
|
@Throws(*<!NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION!>arrayOf(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!><!UNRESOLVED_REFERENCE!>UE<!>::class<!>)<!>)
|
||||||
suspend fun suspendThrowsSpreadArrayOfUnresolved() {}
|
suspend fun suspendThrowsSpreadArrayOfUnresolved() {}
|
||||||
|
|
||||||
@Throws(UEAlias::class)
|
<!MISSING_EXCEPTION_IN_THROWS_ON_SUSPEND!>@Throws(UEAlias::class)<!>
|
||||||
suspend fun suspendThrowsTypealiasToUnresolved() {}
|
suspend fun suspendThrowsTypealiasToUnresolved() {}
|
||||||
|
|
||||||
@Throws(Exception1::class, CancellationException::class)
|
@Throws(Exception1::class, CancellationException::class)
|
||||||
|
|||||||
Reference in New Issue
Block a user