[FIR] Add JVM Default diagnostics

This commit is contained in:
Ivan Kochurkin
2021-08-27 23:17:27 +03:00
committed by TeamCityServer
parent b5ff49c903
commit cfd2835254
36 changed files with 432 additions and 270 deletions
@@ -32,7 +32,6 @@ import org.jetbrains.kotlin.codegen.JvmCodegenUtil
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.config.JvmAnalysisFlags
import org.jetbrains.kotlin.config.JvmTarget
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.load.java.components.JavaDeprecationSettings
@@ -14,6 +14,8 @@ import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.*
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtAnnotationEntry
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtElement
@Suppress("UNUSED_VARIABLE", "LocalVariableName", "ClassName", "unused")
@OptIn(PrivateForInline::class)
@@ -88,4 +90,17 @@ object JVM_DIAGNOSTICS_LIST : DiagnosticList("FirJvmErrors") {
val ILLEGAL_JAVA_LANG_RECORD_SUPERTYPE by error<PsiElement>()
}
val JVM_DEFAULT by object : DiagnosticGroup("JVM Default") {
val JVM_DEFAULT_NOT_IN_INTERFACE by error<PsiElement>()
val JVM_DEFAULT_IN_JVM6_TARGET by error<PsiElement> {
parameter<String>("annotation")
}
val JVM_DEFAULT_REQUIRED_FOR_OVERRIDE by error<KtDeclaration>(PositioningStrategy.DECLARATION_SIGNATURE)
val JVM_DEFAULT_IN_DECLARATION by error<KtElement>(PositioningStrategy.DECLARATION_SIGNATURE_OR_DEFAULT) {
parameter<String>("annotation")
}
val JVM_DEFAULT_THROUGH_INHERITANCE by error<KtDeclaration>(PositioningStrategy.DECLARATION_SIGNATURE)
val USAGE_OF_JVM_DEFAULT_THROUGH_SUPER_CALL by error<PsiElement>()
val NON_JVM_DEFAULT_OVERRIDES_JAVA_DEFAULT by warning<KtDeclaration>(PositioningStrategy.DECLARATION_SIGNATURE)
}
}
@@ -12,6 +12,8 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.SourceElementPositioningStr
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtAnnotationEntry
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtExpression
/*
@@ -72,4 +74,13 @@ object FirJvmErrors {
val JVM_RECORD_EXTENDS_CLASS by error1<PsiElement, ConeKotlinType>(SourceElementPositioningStrategies.ACTUAL_DECLARATION_NAME)
val ILLEGAL_JAVA_LANG_RECORD_SUPERTYPE by error0<PsiElement>()
// JVM Default
val JVM_DEFAULT_NOT_IN_INTERFACE by error0<PsiElement>()
val JVM_DEFAULT_IN_JVM6_TARGET by error1<PsiElement, String>()
val JVM_DEFAULT_REQUIRED_FOR_OVERRIDE by error0<KtDeclaration>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
val JVM_DEFAULT_IN_DECLARATION by error1<KtElement, String>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT)
val JVM_DEFAULT_THROUGH_INHERITANCE by error0<KtDeclaration>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
val USAGE_OF_JVM_DEFAULT_THROUGH_SUPER_CALL by error0<PsiElement>()
val NON_JVM_DEFAULT_OVERRIDES_JAVA_DEFAULT by warning0<KtDeclaration>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
}
@@ -13,6 +13,7 @@ object JvmDeclarationCheckers : DeclarationCheckers() {
get() = setOf(
FirJvmExternalDeclarationChecker,
FirJvmNameChecker,
FirJvmDefaultChecker
)
override val annotatedDeclarationCheckers: Set<FirAnnotatedDeclarationChecker>
@@ -0,0 +1,185 @@
/*
* 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.jvm.checkers.declaration
import org.jetbrains.kotlin.config.JvmDefaultMode
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.context.findClosest
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirBasicDeclarationChecker
import org.jetbrains.kotlin.fir.analysis.checkers.unsubstitutedScope
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
import org.jetbrains.kotlin.fir.containingClass
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.isInterface
import org.jetbrains.kotlin.fir.declarations.utils.modality
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.fir.java.jvmDefaultModeState
import org.jetbrains.kotlin.fir.moduleData
import org.jetbrains.kotlin.fir.resolve.toFirRegularClass
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.scopes.getDirectOverriddenFunctions
import org.jetbrains.kotlin.fir.scopes.impl.FirClassUseSiteMemberScope
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirIntersectionCallableSymbol
import org.jetbrains.kotlin.name.FqName
object FirJvmDefaultChecker : FirBasicDeclarationChecker() {
private val JVM_DEFAULT_FQ_NAME = FqName("kotlin.jvm.JvmDefault")
private val JVM_DEFAULT_NO_COMPATIBILITY_FQ_NAME = FqName("kotlin.jvm.JvmDefaultWithoutCompatibility")
override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
val jvmDefaultMode = context.session.jvmDefaultModeState
var defaultAnnotation: FirAnnotationCall? = null
val containingDeclaration = context.findClosest<FirClassLikeDeclaration>()
if (declaration is FirAnnotatedDeclaration) {
val isJvm16 = context.session.moduleData.platform.componentPlatforms.any { it.targetName == "1.6" }
defaultAnnotation = declaration.getAnnotationByFqName(JVM_DEFAULT_FQ_NAME)
if (defaultAnnotation != null) {
if (containingDeclaration !is FirClass || !containingDeclaration.isInterface) {
reporter.reportOn(defaultAnnotation.source, FirJvmErrors.JVM_DEFAULT_NOT_IN_INTERFACE, context)
return
} else if (isJvm16) {
reporter.reportOn(defaultAnnotation.source, FirJvmErrors.JVM_DEFAULT_IN_JVM6_TARGET, "JvmDefault", context)
return
} else if (!jvmDefaultMode.isEnabled) {
reporter.reportOn(defaultAnnotation.source, FirJvmErrors.JVM_DEFAULT_IN_DECLARATION, "JvmDefault", context)
return
}
} else {
val annotation = declaration.getAnnotationByFqName(JVM_DEFAULT_NO_COMPATIBILITY_FQ_NAME)
if (annotation != null) {
if (isJvm16) {
reporter.reportOn(
annotation.source,
FirJvmErrors.JVM_DEFAULT_IN_JVM6_TARGET,
"JvmDefaultWithoutCompatibility",
context
)
return
} else if (!jvmDefaultMode.isEnabled) {
reporter.reportOn(
annotation.source,
FirJvmErrors.JVM_DEFAULT_IN_DECLARATION,
"JvmDefaultWithoutCompatibility",
context
)
return
}
}
}
}
if (declaration is FirClass) {
val unsubstitutedScope = declaration.unsubstitutedScope(context)
val hasDeclaredJvmDefaults = unsubstitutedScope is FirClassUseSiteMemberScope &&
unsubstitutedScope.directOverriddenFunctions.keys.any {
it.isCompiledToJvmDefault(jvmDefaultMode)
}
if (!hasDeclaredJvmDefaults && !declaration.checkJvmDefaultsInHierarchy(jvmDefaultMode, context)) {
reporter.reportOn(declaration.source, FirJvmErrors.JVM_DEFAULT_THROUGH_INHERITANCE, context)
}
}
checkNonJvmDefaultOverridesJavaDefault(defaultAnnotation, jvmDefaultMode, declaration, containingDeclaration, context, reporter)
}
private fun FirDeclaration.checkJvmDefaultsInHierarchy(jvmDefaultMode: JvmDefaultMode, context: CheckerContext): Boolean {
if (jvmDefaultMode.isEnabled) return true
if (this !is FirClass) return true
val unsubstitutedScope = unsubstitutedScope(context)
if (unsubstitutedScope is FirClassUseSiteMemberScope) {
val directOverriddenFunctions = unsubstitutedScope.directOverriddenFunctions.flatMap { it.value }.toSet()
for (key in unsubstitutedScope.overrideByBase.keys) {
if (directOverriddenFunctions.contains(key)) {
continue
}
if (key.getOverriddenDeclarations().all {
it.containingClass()?.toFirRegularClassSymbol(context.session)?.isInterface != true ||
!it.isCompiledToJvmDefaultWithProperMode(jvmDefaultMode) ||
it.modality == Modality.ABSTRACT
}
) {
continue
}
return false
}
}
return true
}
private fun checkNonJvmDefaultOverridesJavaDefault(
defaultAnnotation: FirAnnotationCall?,
jvmDefaultMode: JvmDefaultMode,
declaration: FirDeclaration,
containingDeclaration: FirClassLikeDeclaration?,
context: CheckerContext,
reporter: DiagnosticReporter
) {
if (defaultAnnotation == null &&
!jvmDefaultMode.forAllMethodsWithBody &&
containingDeclaration is FirClass &&
containingDeclaration.isInterface
) {
val member = declaration as? FirSimpleFunction ?: return
if (declaration is FirPropertyAccessor) return
val unsubstitutedScope = containingDeclaration.unsubstitutedScope(context)
unsubstitutedScope.processFunctionsByName(member.name) {}
val overriddenFunctions = unsubstitutedScope.getDirectOverriddenFunctions(member.symbol)
if (overriddenFunctions.any { it.getAnnotationByFqName(JVM_DEFAULT_FQ_NAME) != null }) {
reporter.reportOn(declaration.source, FirJvmErrors.JVM_DEFAULT_REQUIRED_FOR_OVERRIDE, context)
} else if (jvmDefaultMode.isEnabled) {
for (overriddenFunction in overriddenFunctions) {
val overriddenDeclarations = overriddenFunction.getOverriddenDeclarations()
for (overriddenDeclaration in overriddenDeclarations) {
val containingClass = overriddenDeclaration.containingClass()?.toSymbol(context.session)
if (containingClass?.origin is FirDeclarationOrigin.Java &&
overriddenDeclaration.modality != Modality.ABSTRACT
) {
reporter.reportOn(declaration.source, FirJvmErrors.NON_JVM_DEFAULT_OVERRIDES_JAVA_DEFAULT, context)
return
}
}
}
}
}
}
fun FirCallableSymbol<*>.getOverriddenDeclarations(): List<FirCallableSymbol<*>> {
val result = mutableListOf<FirCallableSymbol<*>>()
if (this is FirIntersectionCallableSymbol) {
result.addAll(this.intersections)
} else {
result.add(this)
}
return result
}
fun FirCallableSymbol<*>.isCompiledToJvmDefaultWithProperMode(jvmDefaultMode: JvmDefaultMode): Boolean {
// TODO: Fix support for all cases
return isCompiledToJvmDefault(jvmDefaultMode)
}
fun FirCallableSymbol<*>.isCompiledToJvmDefault(): Boolean {
// TODO: Fix support for all cases
if (getAnnotationByFqName(JVM_DEFAULT_FQ_NAME) != null) return true
return false
}
}
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.fir.analysis.jvm.diagnostics
import org.jetbrains.kotlin.diagnostics.rendering.CommonRenderers.STRING
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDefaultErrorMessages
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.RENDER_TYPE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.TO_STRING
@@ -18,6 +19,11 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.ILLEGAL_JV
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.INAPPLICABLE_JVM_NAME
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.INNER_JVM_RECORD
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.JAVA_TYPE_MISMATCH
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.JVM_DEFAULT_IN_DECLARATION
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.JVM_DEFAULT_IN_JVM6_TARGET
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.JVM_DEFAULT_NOT_IN_INTERFACE
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.JVM_DEFAULT_REQUIRED_FOR_OVERRIDE
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.JVM_DEFAULT_THROUGH_INHERITANCE
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.JVM_PACKAGE_NAME_CANNOT_BE_EMPTY
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.JVM_PACKAGE_NAME_MUST_BE_VALID_NAME
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.JVM_PACKAGE_NAME_NOT_SUPPORTED_IN_FILES_WITH_CLASSES
@@ -33,6 +39,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.JVM_STATIC
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.LOCAL_JVM_RECORD
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.NON_DATA_CLASS_JVM_RECORD
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.NON_FINAL_JVM_RECORD
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.NON_JVM_DEFAULT_OVERRIDES_JAVA_DEFAULT
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.OVERLOADS_ABSTRACT
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.OVERLOADS_ANNOTATION_CLASS_CONSTRUCTOR
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.OVERLOADS_INTERFACE
@@ -46,6 +53,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.SYNCHRONIZ
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.SYNCHRONIZED_ON_ABSTRACT
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.SYNCHRONIZED_ON_INLINE
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.UPPER_BOUND_CANNOT_BE_ARRAY
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.USAGE_OF_JVM_DEFAULT_THROUGH_SUPER_CALL
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.VOLATILE_ON_DELEGATE
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.VOLATILE_ON_VALUE
@@ -126,6 +134,27 @@ object FirJvmDefaultErrorMessages {
map.put(INAPPLICABLE_JVM_NAME, "'@JvmName' annotation is not applicable to this declaration")
map.put(ILLEGAL_JVM_NAME, "Illegal JVM name")
map.put(JVM_DEFAULT_NOT_IN_INTERFACE, "'@JvmDefault' is only supported on interface members")
map.put(
JVM_DEFAULT_IN_JVM6_TARGET,
"''@{0}'' is only supported since JVM target 1.8. Recompile with ''-jvm-target 1.8''",
STRING
)
map.put(JVM_DEFAULT_REQUIRED_FOR_OVERRIDE, "'@JvmDefault' is required for an override of a '@JvmDefault' member")
map.put(JVM_DEFAULT_IN_DECLARATION, "Usage of ''@{0}'' is only allowed with -Xjvm-default option", STRING)
map.put(
JVM_DEFAULT_THROUGH_INHERITANCE,
"Inheritance from an interface with '@JvmDefault' members is only allowed with -Xjvm-default option"
)
map.put(
USAGE_OF_JVM_DEFAULT_THROUGH_SUPER_CALL,
"Super calls of '@JvmDefault' members are only allowed with -Xjvm-default option"
)
map.put(
NON_JVM_DEFAULT_OVERRIDES_JAVA_DEFAULT,
"Non-@JvmDefault interface method cannot override default Java method. Please annotate this method with @JvmDefault or enable `-Xjvm-default=all|all-compatibility`"
)
}
}
}
@@ -27,7 +27,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
FirExposedVisibilityDeclarationChecker,
FirCyclicTypeBoundsChecker,
FirExpectActualDeclarationChecker,
FirInvalidAndDangerousCharactersChecker
FirInvalidAndDangerousCharactersChecker,
)
override val functionCheckers: Set<FirFunctionChecker>
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.fir.extensions.FirPredicateBasedProvider
import org.jetbrains.kotlin.fir.extensions.FirRegisteredPluginAnnotations
import org.jetbrains.kotlin.fir.java.FirJavaVisibilityChecker
import org.jetbrains.kotlin.fir.java.enhancement.FirAnnotationTypeQualifierResolver
import org.jetbrains.kotlin.fir.java.FirJvmDefaultModeComponent
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.calls.ConeCallConflictResolverFactory
import org.jetbrains.kotlin.fir.resolve.calls.FirSyntheticNamesProvider
@@ -71,6 +72,10 @@ fun FirSession.registerCliCompilerOnlyComponents() {
fun FirSession.registerCommonJavaComponents(javaModuleResolver: JavaModuleResolver) {
val jsr305State = languageVersionSettings.getFlag(JvmAnalysisFlags.javaTypeEnhancementState)
register(FirAnnotationTypeQualifierResolver::class, FirAnnotationTypeQualifierResolver(this, jsr305State, javaModuleResolver))
register(
FirJvmDefaultModeComponent::class,
FirJvmDefaultModeComponent(languageVersionSettings.getFlag(JvmAnalysisFlags.jvmDefaultMode))
)
}
// -------------------------- Resolve components --------------------------
@@ -0,0 +1,17 @@
/*
* 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.java
import org.jetbrains.kotlin.config.JvmDefaultMode
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.FirSessionComponent
class FirJvmDefaultModeComponent(val jvmDefaultMode: JvmDefaultMode) : FirSessionComponent
private val FirSession.jvmDefaultModeComponent: FirJvmDefaultModeComponent by FirSession.sessionComponentAccessor()
val FirSession.jvmDefaultModeState: JvmDefaultMode
get() = jvmDefaultModeComponent.jvmDefaultMode
@@ -19,7 +19,7 @@ abstract class AbstractFirUseSiteMemberScope(
) : AbstractFirOverrideScope(session, overrideChecker) {
private val functions = hashMapOf<Name, Collection<FirNamedFunctionSymbol>>()
protected val directOverriddenFunctions = hashMapOf<FirNamedFunctionSymbol, Collection<FirNamedFunctionSymbol>>()
val directOverriddenFunctions = hashMapOf<FirNamedFunctionSymbol, Collection<FirNamedFunctionSymbol>>()
protected val directOverriddenProperties = hashMapOf<FirPropertySymbol, MutableList<FirPropertySymbol>>()
private val callableNamesCached by lazy(LazyThreadSafetyMode.PUBLICATION) {
@@ -1,60 +0,0 @@
// !JVM_TARGET: 1.8
// !JVM_DEFAULT_MODE: enable
interface A<T> {
@<!DEPRECATION!>JvmDefault<!>
fun test(p: T) {
}
}
interface ANonDefault {
fun test(p: String) {}
}
interface B<T> : A<T> {
override fun test(p: T)
{}
}
interface C<T> : A<T>, ANonDefault {
override fun test(p: T)
{}
override fun test(p: String) {
}
}
interface C1 : C<String> {
override fun test(p: String) {
}
}
interface C2 : C<String>, ANonDefault {
override fun test(p: String) {
}
}
interface D<T> : ANonDefault, A<T> {
override fun test(p: T)
{}
override fun test(p: String) {
}
}
interface D1 : D<String> {
override fun test(p: String) {
}
}
interface D2 : ANonDefault, D<String> {
override fun test(p: String) {
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !JVM_TARGET: 1.8
// !JVM_DEFAULT_MODE: enable
@@ -1,72 +0,0 @@
// !JVM_DEFAULT_MODE: enable
// !JVM_TARGET: 1.8
// FILE: JavaInterface.java
public interface JavaInterface {
default void test() {}
default void testForNonDefault() {}
void testAbstract();
}
// FILE: 1.kt
interface KotlinInterface : JavaInterface {
@<!DEPRECATION!>JvmDefault<!>
override fun test() {}
override fun testForNonDefault() {}
override fun testAbstract() {}
}
interface KotlinInterface2 : JavaInterface, KotlinInterface {
@<!DEPRECATION!>JvmDefault<!>
override fun test() {}
override fun testForNonDefault() {}
override fun testAbstract() {}
}
interface KotlinInterfaceForIndirect : JavaInterface {
}
interface KotlinInterfaceIndirectInheritance : KotlinInterfaceForIndirect {
@<!DEPRECATION!>JvmDefault<!>
override fun test() {}
override fun testForNonDefault() {}
override fun testAbstract() {}
}
open class KotlinClass : JavaInterface {
override fun test() {}
override fun testForNonDefault() {}
override fun testAbstract() {}
}
interface KotlinInterfaceX {
fun test() {}
fun testForNonDefault() {}
fun testAbstract() {}
}
interface KotlinInterfaceManySuper: JavaInterface, KotlinInterfaceX {
@<!DEPRECATION!>JvmDefault<!>
override fun test() {}
override fun testForNonDefault() {}
override fun testAbstract() {}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !JVM_DEFAULT_MODE: enable
// !JVM_TARGET: 1.8
@@ -1,18 +1,17 @@
// !JVM_TARGET: 1.8
interface A {
@<!DEPRECATION!>JvmDefault<!>
<!JVM_DEFAULT_IN_DECLARATION!>@<!DEPRECATION!>JvmDefault<!><!>
fun test() {
}
}
interface B : A {
interface <!JVM_DEFAULT_THROUGH_INHERITANCE!>B<!> : A {
}
open class Foo : B
open class Foo2 : B, A
open class <!JVM_DEFAULT_THROUGH_INHERITANCE!>Foo<!> : B
open class <!JVM_DEFAULT_THROUGH_INHERITANCE!>Foo2<!> : B, A
open class FooNoError : B {
override fun test() {
@@ -23,12 +22,12 @@ open class Foo2NoError : B, A {
}
}
class Bar : Foo()
class Bar2 : Foo(), A
class Bar3 : Foo(), B
class <!JVM_DEFAULT_THROUGH_INHERITANCE!>Bar<!> : Foo()
class <!JVM_DEFAULT_THROUGH_INHERITANCE!>Bar2<!> : Foo(), A
class <!JVM_DEFAULT_THROUGH_INHERITANCE!>Bar3<!> : Foo(), B
open class BarWithJvmDefault : B {
@<!DEPRECATION!>JvmDefault<!>
<!JVM_DEFAULT_NOT_IN_INTERFACE!>@<!DEPRECATION!>JvmDefault<!><!>
override fun test() {
}
}
@@ -7,7 +7,6 @@ interface A {
}
interface <!JVM_DEFAULT_THROUGH_INHERITANCE!>B<!> : A {
}
@@ -1,7 +0,0 @@
// !JVM_TARGET: 1.6
@JvmDefaultWithoutCompatibility
interface A {}
@JvmDefaultWithoutCompatibility
class B : A {}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !JVM_TARGET: 1.6
<!JVM_DEFAULT_IN_JVM6_TARGET!>@JvmDefaultWithoutCompatibility<!>
@@ -1,9 +0,0 @@
// !JVM_TARGET: 1.8
@JvmDefaultWithoutCompatibility
interface A<T> {
fun test(p: T) {}
}
@JvmDefaultWithoutCompatibility
class B : A<String> {}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !JVM_TARGET: 1.8
<!JVM_DEFAULT_IN_DECLARATION!>@JvmDefaultWithoutCompatibility<!>
@@ -2,27 +2,27 @@
interface B {
@<!DEPRECATION!>JvmDefault<!>
<!JVM_DEFAULT_IN_DECLARATION!>@<!DEPRECATION!>JvmDefault<!><!>
fun test() {}
@<!DEPRECATION!>JvmDefault<!>
<!JVM_DEFAULT_IN_DECLARATION!>@<!DEPRECATION!>JvmDefault<!><!>
abstract fun test2(s: String = "")
@<!DEPRECATION!>JvmDefault<!>
<!JVM_DEFAULT_IN_DECLARATION!>@<!DEPRECATION!>JvmDefault<!><!>
abstract fun test3()
@<!DEPRECATION!>JvmDefault<!>
<!JVM_DEFAULT_IN_DECLARATION!>@<!DEPRECATION!>JvmDefault<!><!>
abstract val prop: String
@<!DEPRECATION!>JvmDefault<!>
<!JVM_DEFAULT_IN_DECLARATION!>@<!DEPRECATION!>JvmDefault<!><!>
abstract val prop2: String
@<!DEPRECATION!>JvmDefault<!>
<!JVM_DEFAULT_IN_DECLARATION!>@<!DEPRECATION!>JvmDefault<!><!>
val prop3: String
get() = ""
@<!DEPRECATION!>JvmDefault<!>
<!JVM_DEFAULT_IN_DECLARATION!>@<!DEPRECATION!>JvmDefault<!><!>
var prop4: String
get() = ""
set(value) {}
@@ -1,22 +0,0 @@
// !JVM_TARGET: 1.8
abstract class A {
@<!DEPRECATION!>JvmDefault<!>
fun test() {}
@<!DEPRECATION!>JvmDefault<!>
abstract fun test2(s: String = "")
@<!DEPRECATION!>JvmDefault<!>
abstract fun test3()
}
object B {
@<!DEPRECATION!>JvmDefault<!>
fun test() {}
@<!DEPRECATION!>JvmDefault<!>
fun test2(s: String = "") {}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !JVM_TARGET: 1.8
abstract class A {
@@ -1,31 +0,0 @@
// !JVM_TARGET: 1.8
// !JVM_DEFAULT_MODE: enable
interface A {
@<!DEPRECATION!>JvmDefault<!>
fun test() {}
}
interface Abstract : A {
override fun test()
}
interface ANonDefault {
fun test() {}
}
interface B: A {
override fun test() {}
}
interface C: ANonDefault, A {
override fun test() {}
}
interface D: A, ANonDefault {
override fun test() {}
}
class Foo : A {
override fun test() {}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !JVM_TARGET: 1.8
// !JVM_DEFAULT_MODE: enable
@@ -1,18 +1,18 @@
// !JVM_TARGET: 1.8
// FILE: 1.kt
interface A {
@<!DEPRECATION!>JvmDefault<!>
<!JVM_DEFAULT_IN_DECLARATION!>@<!DEPRECATION!>JvmDefault<!><!>
fun test() {
}
}
// FILE: 2.kt
interface B : A {
interface <!JVM_DEFAULT_THROUGH_INHERITANCE!>B<!> : A {
}
interface C : B {
@<!DEPRECATION!>JvmDefault<!>
<!JVM_DEFAULT_IN_DECLARATION!>@<!DEPRECATION!>JvmDefault<!><!>
override fun test() {
super.test()
}
@@ -23,7 +23,7 @@ open class Foo : B {
super.test()
}
}
open class Foo2 : B
open class <!JVM_DEFAULT_THROUGH_INHERITANCE!>Foo2<!> : B
open class Bar : Foo2() {
override fun test() {
@@ -37,7 +37,7 @@ open class Bar2 : Bar() {
}
}
class ManySupers: Foo2(), B {
class <!JVM_DEFAULT_THROUGH_INHERITANCE!>ManySupers<!>: Foo2(), B {
fun foo() {
super<Foo2>.test()
super<<!QUALIFIED_SUPERTYPE_EXTENDED_BY_OTHER_SUPERTYPE!>B<!>>.test()
@@ -45,7 +45,7 @@ class ManySupers: Foo2(), B {
}
}
class ManySupers2: Foo2(), C {
class <!JVM_DEFAULT_THROUGH_INHERITANCE!>ManySupers2<!>: Foo2(), C {
fun foo() {
super<Foo2>.test()
super<C>.test()
@@ -53,7 +53,7 @@ class ManySupers2: Foo2(), C {
}
}
<!MANY_IMPL_MEMBER_NOT_IMPLEMENTED!>class ManySupers3<!>: Bar2(), C {
<!MANY_IMPL_MEMBER_NOT_IMPLEMENTED!>class <!JVM_DEFAULT_THROUGH_INHERITANCE!>ManySupers3<!><!>: Bar2(), C {
fun foo() {
super<Bar2>.test()
super<C>.test()
@@ -1,6 +1,6 @@
// !JVM_TARGET: 1.8
interface A {
@<!DEPRECATION!>JvmDefault<!>
<!JVM_DEFAULT_IN_DECLARATION!>@<!DEPRECATION!>JvmDefault<!><!>
fun test() {
}
}
@@ -10,13 +10,13 @@ interface B{
}
}
<!MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED!>interface AB<!>: A, B
<!MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED!>interface <!JVM_DEFAULT_THROUGH_INHERITANCE!>AB<!><!>: A, B
<!MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED!>interface BA<!>: B, A
<!MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED!>interface <!JVM_DEFAULT_THROUGH_INHERITANCE!>BA<!><!>: B, A
interface C : A, B {
@<!DEPRECATION!>JvmDefault<!>
<!JVM_DEFAULT_IN_DECLARATION!>@<!DEPRECATION!>JvmDefault<!><!>
override fun test() {
super<B>.test()
super<A>.test()
@@ -24,9 +24,9 @@ interface C : A, B {
}
interface D : B, A {
@<!DEPRECATION!>JvmDefault<!>
<!JVM_DEFAULT_IN_DECLARATION!>@<!DEPRECATION!>JvmDefault<!><!>
override fun test() {
super<B>.test()
super<A>.test()
}
}
}
@@ -1,6 +1,6 @@
// !JVM_TARGET: 1.8
interface A {
@<!DEPRECATION!>JvmDefault<!>
<!JVM_DEFAULT_IN_DECLARATION!>@<!DEPRECATION!>JvmDefault<!><!>
fun test()
}
@@ -29,4 +29,4 @@ class D : B, A {
fun foo() {
super<B>.test()
}
}
}
@@ -1,6 +1,6 @@
// !JVM_TARGET: 1.8
interface A {
@<!DEPRECATION!>JvmDefault<!>
<!JVM_DEFAULT_IN_DECLARATION!>@<!DEPRECATION!>JvmDefault<!><!>
fun test() {
}
@@ -9,8 +9,8 @@ interface A {
interface B{
fun test()
}
<!MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED!>interface AB<!> : A, B
<!MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED!>interface BA<!> : B, A
<!MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED!>interface <!JVM_DEFAULT_THROUGH_INHERITANCE!>AB<!><!> : A, B
<!MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED!>interface <!JVM_DEFAULT_THROUGH_INHERITANCE!>BA<!><!> : B, A
class C : A, B {
override fun test() {
@@ -24,8 +24,8 @@ class D : B, A {
}
}
<!MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED!>class E<!>: B, A {
<!MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED!>class <!JVM_DEFAULT_THROUGH_INHERITANCE!>E<!><!>: B, A {
fun foo() {
super<A>.test()
}
}
}
@@ -1,29 +0,0 @@
// !JVM_TARGET: 1.6
interface B {
@<!DEPRECATION!>JvmDefault<!>
fun test() {}
@<!DEPRECATION!>JvmDefault<!>
abstract fun test2(s: String = "")
@<!DEPRECATION!>JvmDefault<!>
abstract fun test3()
@<!DEPRECATION!>JvmDefault<!>
abstract val prop: String
@<!DEPRECATION!>JvmDefault<!>
abstract val prop2: String
@<!DEPRECATION!>JvmDefault<!>
val prop3: String
get() = ""
@<!DEPRECATION!>JvmDefault<!>
var prop4: String
get() = ""
set(value) {}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !JVM_TARGET: 1.6
interface B {
@@ -3712,4 +3712,48 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token,
)
}
add(FirJvmErrors.JVM_DEFAULT_NOT_IN_INTERFACE) { firDiagnostic ->
JvmDefaultNotInInterfaceImpl(
firDiagnostic as FirPsiDiagnostic,
token,
)
}
add(FirJvmErrors.JVM_DEFAULT_IN_JVM6_TARGET) { firDiagnostic ->
JvmDefaultInJvm6TargetImpl(
firDiagnostic.a,
firDiagnostic as FirPsiDiagnostic,
token,
)
}
add(FirJvmErrors.JVM_DEFAULT_REQUIRED_FOR_OVERRIDE) { firDiagnostic ->
JvmDefaultRequiredForOverrideImpl(
firDiagnostic as FirPsiDiagnostic,
token,
)
}
add(FirJvmErrors.JVM_DEFAULT_IN_DECLARATION) { firDiagnostic ->
JvmDefaultInDeclarationImpl(
firDiagnostic.a,
firDiagnostic as FirPsiDiagnostic,
token,
)
}
add(FirJvmErrors.JVM_DEFAULT_THROUGH_INHERITANCE) { firDiagnostic ->
JvmDefaultThroughInheritanceImpl(
firDiagnostic as FirPsiDiagnostic,
token,
)
}
add(FirJvmErrors.USAGE_OF_JVM_DEFAULT_THROUGH_SUPER_CALL) { firDiagnostic ->
UsageOfJvmDefaultThroughSuperCallImpl(
firDiagnostic as FirPsiDiagnostic,
token,
)
}
add(FirJvmErrors.NON_JVM_DEFAULT_OVERRIDES_JAVA_DEFAULT) { firDiagnostic ->
NonJvmDefaultOverridesJavaDefaultImpl(
firDiagnostic as FirPsiDiagnostic,
token,
)
}
}
@@ -2582,4 +2582,34 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
override val diagnosticClass get() = IllegalJavaLangRecordSupertype::class
}
abstract class JvmDefaultNotInInterface : KtFirDiagnostic<PsiElement>() {
override val diagnosticClass get() = JvmDefaultNotInInterface::class
}
abstract class JvmDefaultInJvm6Target : KtFirDiagnostic<PsiElement>() {
override val diagnosticClass get() = JvmDefaultInJvm6Target::class
abstract val annotation: String
}
abstract class JvmDefaultRequiredForOverride : KtFirDiagnostic<KtDeclaration>() {
override val diagnosticClass get() = JvmDefaultRequiredForOverride::class
}
abstract class JvmDefaultInDeclaration : KtFirDiagnostic<KtElement>() {
override val diagnosticClass get() = JvmDefaultInDeclaration::class
abstract val annotation: String
}
abstract class JvmDefaultThroughInheritance : KtFirDiagnostic<KtDeclaration>() {
override val diagnosticClass get() = JvmDefaultThroughInheritance::class
}
abstract class UsageOfJvmDefaultThroughSuperCall : KtFirDiagnostic<PsiElement>() {
override val diagnosticClass get() = UsageOfJvmDefaultThroughSuperCall::class
}
abstract class NonJvmDefaultOverridesJavaDefault : KtFirDiagnostic<KtDeclaration>() {
override val diagnosticClass get() = NonJvmDefaultOverridesJavaDefault::class
}
}
@@ -4194,3 +4194,54 @@ internal class IllegalJavaLangRecordSupertypeImpl(
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
}
internal class JvmDefaultNotInInterfaceImpl(
firDiagnostic: FirPsiDiagnostic,
override val token: ValidityToken,
) : KtFirDiagnostic.JvmDefaultNotInInterface(), KtAbstractFirDiagnostic<PsiElement> {
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
}
internal class JvmDefaultInJvm6TargetImpl(
override val annotation: String,
firDiagnostic: FirPsiDiagnostic,
override val token: ValidityToken,
) : KtFirDiagnostic.JvmDefaultInJvm6Target(), KtAbstractFirDiagnostic<PsiElement> {
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
}
internal class JvmDefaultRequiredForOverrideImpl(
firDiagnostic: FirPsiDiagnostic,
override val token: ValidityToken,
) : KtFirDiagnostic.JvmDefaultRequiredForOverride(), KtAbstractFirDiagnostic<KtDeclaration> {
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
}
internal class JvmDefaultInDeclarationImpl(
override val annotation: String,
firDiagnostic: FirPsiDiagnostic,
override val token: ValidityToken,
) : KtFirDiagnostic.JvmDefaultInDeclaration(), KtAbstractFirDiagnostic<KtElement> {
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
}
internal class JvmDefaultThroughInheritanceImpl(
firDiagnostic: FirPsiDiagnostic,
override val token: ValidityToken,
) : KtFirDiagnostic.JvmDefaultThroughInheritance(), KtAbstractFirDiagnostic<KtDeclaration> {
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
}
internal class UsageOfJvmDefaultThroughSuperCallImpl(
firDiagnostic: FirPsiDiagnostic,
override val token: ValidityToken,
) : KtFirDiagnostic.UsageOfJvmDefaultThroughSuperCall(), KtAbstractFirDiagnostic<PsiElement> {
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
}
internal class NonJvmDefaultOverridesJavaDefaultImpl(
firDiagnostic: FirPsiDiagnostic,
override val token: ValidityToken,
) : KtFirDiagnostic.NonJvmDefaultOverridesJavaDefault(), KtAbstractFirDiagnostic<KtDeclaration> {
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
}